快速幂
前言
本蒟蒻最近刚好刷完搜索部分,该刷分治算法了。第一题就是快速幂的模板题,今天我就顺着这道题讲讲刚学来的快速幂算法(话说快速幂好像没用到分治啊)吧。(写得不好勿喷)
原理
如果你要用电脑计算\(a^b\),怎样快速求出解呢?
最容易想到的就是暴力运算\(b\)次,思路是简单,可惜速度不快。而相比较下,快速幂的速度就很快了。(看名字)
比如你想计算\(3^{13}\),\(13\)在二进制下\((1101)_2\),所以\(13\)就可以表示为\(2^0+2^2+2^3\),根据\(a^{x+y}=a^x\times{a^y}\)可以推导出:
\(3^{13}=3^{2^0+2^2+2^3}=3^{2^0}\times{3^{2^2}}\times{3^{2^3}}\)
也就是将\(a^b\)变为多个\(a^{2^n}\)相乘的形式(\(n\)为二进制下\(1\)所在的位)
实现
讲完了原理,实现也就不难了。
首先我们要检查二进制每一位是否为\(1\),将\(a\)自乘来表示\(a^{2^n}\),即每检查一位就自乘一次,如果该位为\(1\)就乘到答案(\(ans\))上
介绍一下c++下的位运算:
/*
>> 右移运算
比如1101001右移一位得到110100(最后一位没了)
& 与
这里运用&1,若最后一位为1就返回1,最后一位为0就返回0,起到检查位的作用
*/
所以我们不断用>>右移直到只剩下0,并用&来检查每一位是否为\(1\)。
代码实现:
long long quickpow(long long a,long long b)
{
long long ans=1; //用来储存答案
while(b>0) //循环,检查每一位
{
if(b&1) ans*=a; //这一位为1,乘上a^2^n
a*=a; //自乘,表示a^2^n
b>>=1; //右移,下一位
}
return ans; //返回答案
}
例题讲解
洛谷P1226【模板】快速幂||取余运算
输入\(b,p,k\),输出\(b^p\bmod{k}\)。
这似乎可以直接输出\(ans\bmod{k}\),但这样做会爆long long。
根据性质\((x\times{y})\bmod{z}=[(x\bmod{z})\times{(y\bmod{z})}]\bmod{z}\),所以我们应该对每步运算取模(等同于对结果取模)。
long long quickpow(long long a,long long b,int m) //增加参数m,计算a^b mod m
{
long long ans=1;
while(b>0)
{
if(b&1)
{
ans*=a;
ans%=m; //取模
}
a*=a;
a%=m; //取模
b>>=1;
}
return ans%m; //也要进行取模
}
注意:最终结果要再进行一次取模,例如计算\(2^0\bmod{1}\),如果不取模就会返回1(正确答案是0)。

浙公网安备 33010602011771号