在 int32 的存储条件下,大数计算乘法,可能会超出数值范围,导致返回值错误
1. 循环求余法
把指数操作转换成一次次的乘法,每次相乘就取以此余数,使得数值不超过范围
// 求 (x^a) % p —— 循环求余法
public int remainder(x, a, p){
int rem = 1;
while(a--){
rem = (rem * x) % p;
}
return rem;
}
2. 快速幂取余
计算a^n % b,其中a,b和n都是32位的整数。例如 2^31 % 3 = 2,例如 100^1000 % 1000 = 0
用快速幂的方法时间复杂度可以达到O(logn)
快速幂思想:x^2 = x * x;x^4 = x^2 * x2;x8 = x^4 * x^4……
快速幂代码
public static int fastPow(int a, int b) {
int ans = 1;
int base = a;
while(b != 0) {
if ((b & 1) != 0) {
ans = ans * base;
}
base *= base;
b >>= 1;
}
return ans;
}
然而这里不是简单的快速幂,还要取模.其实也挺简单,先把计算过程中的变量 ans 和 base 的数据类型改成 long ,防止数值越界,然后就是在计算乘法的时候,再加一步取模
public static int fastPow(int a, int b. int n) {
if (n == 0) { // 规定模 0 是什么
return 1 % b;
}
long ans = 1;
long base = a;
while(b != 0) {
if ((b & 1) != 0) {
ans = (ans * base) % n;
}
base = (base % n) * (base % n);
b >>= 1;
}
return (int)ans;
}