版权声明:本文为博主原创文章,未经博主允许不得转载qwq。https://blog.csdn.net/flora715 https://blog.csdn.net/flora715/article/details/82343372
快速幂引入
while(b > 0){
if(b & 1)
ans *= base;
/*询问此时b(二进制)的最后一位是 1 吗? 是的。
这代表 a^{11} = a^8 × a^2 × a^1 中的“ × a^1 ”存在。
所以 ans∗=base。注意,base的值是会流动的。 */
/*关于 b & 1:“按位与”。
x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
与运算,即两者都为 1 时才会返回 1,否则返回 0。
二进制
b = 1011
1 = 0001
b&1 = 0001
因为 1(二进制)的前面几位全部都是 0,所以不会影响前面。
当 b 二进制最后一位是 1 时,b & 1 才会返回 1。*/
base *= base; //然后 base 倍增,通过自乘一次,使自己变成 a^2 。
b >>= 1; //进行之后,b=(101)2
//把(二进制下的)自己每一位都往右移动了。原来的最后第二位,变成了最后第一位。
}
【代码综合实现】
一行代码:
ll power(ll a,ll b){ //快速幂
ll anss=1; while(b) anss=anss*(b&1?a:1)%p,a=a*a%p,b>>=1; return anss;
}
带注解代码:
ll power(ll a,ll b,ll m){ //求a的b次方%m
ll ans=1; //ans为答案
while(b>0){ //b是不断右移的二进制数
if(b&1) //&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
ans=(ll)ans*a%m; //把ans乘上对应的a^(2^i)
a=(ll)a*a%m; //a自乘,由a^(2^i)变成a^(2^(i+1))
b>>=1; //位运算,b右移一位
}
return ans;
}
取余运算
快速幂经常要结合取余运算。这里也讲一点。
取余运算有一些好用的性质,包括:
while(b > 0){
if(b & 1){
ans *= base;
ans %= m; //边乘边余
}
base *= base;
base %= m; //边乘边余
b >>= 1;
}
——时间划过风的轨迹,那个少年,还在等你。