前言
在计算大整数的很高次幂的时候会遇到计算时间过长的情况,还可能超出数值的表达范围,在这里引入快速幂算法
分析思路
取模
假如我们要计算x的n次然后取模p,即(x^n)%p
假如
x = p * m1 + n1
y = p * m2 + n2
其中 n1和n2都是不大于p的整数 (也就是说x对p取模,结果肯定是不大于p的)
即 x%p = n1
即 y%p = n2
在计算 (x*y)%p 就变成了 (m1*m2*p^2 +p*m1*n2+p*m2*n1+n1*n2)%p
很明显多项式
(1) (m1*m2*p^2)%p=0
(2) (p*m1*n2)%p=0
(3) (p*m2*n1)%p=0
最后只剩下了(n1*n2)%p
综上所述:
(x*y)%p=((x%p)*(y%p))%p
快速幂
举个例子:
在计算2^5时候 可以写成(2^1) * (2^4)
也就是 2^1,2^2,2^3,…
5的二进制是101 从右往左看
1.第一位是1 : 2^5 需要 2^1
2.第二位是0 : 2^5 不需要 2^2
3.第三位是1 : 2^5 需要 2^4
2^14 = (2^2) * (2^4) * (2^8)
14的二进制是1110 从右往左看
1.第一位是0 : 2^14 不需要 2^1
2.第二位是1 : 2^14 需要 2^2
3.第三位是1 : 2^14 需要 2^4
4.第四位是1 : 2^14 需要2^8
在这种思路下只需要 log2(n)次计算完成
上代码
计算 (x^n)%p
using ll = long long;
ll f(int x,int n,int p){
int ret = 1;
while (n){
if (n%2){ //如果这个二进制位是1,说明需要取值
ret = ((ret%p)*(x%p))%p;
}
x*=x; //对应二进制位的次数
n/=2;
}
return ret;
}