快速幂:
累乘求 a^b 的时间复杂度是O( n ),快速幂可以在 O( log(n) ) 的时间复杂度下求 a^b 的值。
1.快速幂思路
首先,可以利用 2^0 ,2^1,2^2 ...... 2^(n -1) 组合出 1~2^n 内的任何数;
例如:bin(13) = 1101,那么 13 = 2^0 + 2^2 + 2^3。
现在,求 a^b%p,将b看做二进制形式, 即a^bin(b)%p ;
再将b分解,只需要预处理出 a^(2^0),a^(2^1)....a^(2^k) 即可;
例如:2^13 = 2^bin(1101) = 2^(2^0) * 2^(2^2) * 2^(2^3);
时间复杂度为 O( long(n) )。
2.代码模板如下:
typedef long long LL;
LL quick_pow(LL a, LL b, LL p) {
LL res = 1;
while (b) {
//异或运算,b&1即判断b的最小位上的数是否为1
if (b & 1)res = res * a % p;
a = a * a % p;
//右移运算符,即舍弃b的最小位
b >>= 1;
}
return res;
}
快速幂求逆元:
1.逆元:
在除法运算中,(a/b)%c != (a%c) / (b%c);
假设 b%c 的乘法逆元为 ni (b%c),则 (a/b)%c = (a%c) * ni(b%c);
ni(b%c) = (b^c-2)%c,用快速幂求即可。
2.代码模板如下:
LL quick_pow(LL a,LL b,LL c){
LL res=1;
while(b){
if(b&1)res=res*a%c;
a=a*a%c;
b>>=1;
}
return res;
}
cout<<quick_pow(a,b-2,b)//求a%b的逆元