一:用处:
1.顾名思义,即快速计算幂。对于普通的pow函数,时间复杂度为O(n),因为有n个自身相乘嘛,但是对于快速幂呢,他可以将复杂度降为logn,快好多,这个logn咋算的呢,我没仔细想过,博主太菜了,见谅。
2.对于一个幂算出来极大的数,for example:2^200,这样的数,明显没办法用 long long /int来存放,假如要将该数对一个数取模,势必用到字符串操作方式,想想都麻烦,更别说敲代码了,再者,假如是对一个1e9+7这样大的数取模,则更是emmmm,反正博主太菜了,没想过怎么处理。这时候快速幂就派上用场了。再结合几个数学公式即可解决。
二:代码及解释:
这是我从别人博客复制过来的,因为懒得自己敲了。。
比如计算 3^11,因为11的二进制可表示为1011,则根据数学推理可知:
3^11=3^(2^3+2^1+2^0)=3^(2^3)*3^(2^1)*3^(2^0)
int powadvance(int a,int b){//a是3 b是11
int ans=1,base=a;//ans是放答案的,base是2的n次方
while(b!=0){//即b化为二进制后,没有被读取完时执行
if(b&1!=0)//对化为二进制的b的最后一位检测,看他是不是0,是1的时候执行步骤
ans*=base;//即按第三个等式从右到左的顺序依次出现从右到左的三个项
base*=base;//对2的n次方进行更新
b>>=1;//去掉化为二进制的b的最后一位二进制数,来更新b,即原先为1011,下一轮循环的时候为101
}
return ans;
}
最好拿纸笔手算模拟一遍,比较好理解。
快速幂的算法就是如上所示了,再对他进行和取模操作合并
三:快速幂取模
1.数学背景:
运算规则
模运算与基本四则运算有些相似,但是除法例外。其规则如下:
-
(a + b) % p = (a % p + b % p) % p (1)
-
(a - b) % p = (a % p - b % p) % p (2)
-
(a * b) % p = (a % p * b % p) % p (3)
-
a ^ b % p = ((a % p)^b) % p (4)
-
结合律:
-
((a+b) % p + c) % p = (a + (b+c) % p) % p (5)
((a*b) % p * c)% p = (a * (b*c) % p) % p (6)
-
交换律:
(a + b) % p = (b+a) % p (7)
(a * b) % p = (b * a) % p (8)
-
分配律:
(a+b) % p = ( a % p + b % p ) % p (9)
((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (10)
以上是百度百科复制来的,四条基本规则比较重要一些。由基本规则可知,若想对幂取模,可对快速幂做以下的修改。
long long quick(long long a,int b,long long c) //a是3,b是11,c是1e9+7
{
long long ans=1;
while(b!=0)
{
if(b&1!=0){
ans=(ans*a)%c;//不一样的地方,由基本规则3可得,手动模拟一波即可
}
b>>=1;
a=(a*a)%c;//由基本规则3可得
}
return ans;
}