我们知道,求幂运算的方法
int ans=1;
for(int i=1;i<=power;i++)
ans*=base;
不过这样有个问题,就是在(2,32)的时候就会爆int 而long long 也在(2,64)的时候不能幸免,所以很多时候我们求的是幂运算的mod后的结果比如这样写
int ans=1;
for(int i=1;i<=power;i++)
ans*=base%mod;
就可以解决数据范围的问题,但是当power很大的时候,时间就成了约束条件,如当power为1e9时,时间达到了15s。那么我们如何解决这样问题呢?
快速幂就派上用场了
我们知道时间慢的原因是因为乘的动作循环了1e9次,我们要想优化,必须把乘的次数减少。快速幂的关键就在这
比如2100=(22)50
我们用50+1次操作替代了100次操作,同时我们可以继续递归下去减少时间
(22)50=((22)2)25
用25+2次操作替代了51次
那么接下来应当怎么做呢25无法再整除2了,因此我们可以把它变成((22)2)24+1=(22)2)24 * (22)2)=(((22)2)2)12 * (22)2
在编程中如何实现呢?
用位运算比较容易理解,比如pow(2,9),9用二进制表示为10001,2power=(22)power/2,可以通过每次power/=2.base*=base来化简,如果二进制最后一位为1,那么不能直接化简要把1提出来,就是ans要乘以base。
int q_pow(int base,int power,int mod)
{
int ans=1;
while(power)
{
if(power&1)
ans=ans*base%mod;
base=base*base%1000;
power>>=1;
}
return ans;
}
十分快的得到了结果
和快速幂类似,如果直接乘会爆long long,那么可以用慢速乘
ll q_mul(ll x,ll y,ll mod)
{
ll ans=1;
while(y)
{
if(y&1) ans=(ans+x)%mod;
x=(x*2)%mod;
y>>=1;
}
return ans;
}