何为快速幂
我们以洛谷P1226【快速幂】为例
最简单的做法就是直接暴力
#include<bits/stdc++.h>
using namespace std;
int main(){
long long a,b,p;
cin>>a>>b>>p;
long long ans=1;
for(int i=0;i<b;i++){
ans*=a;
}
cout<<ans;
}
但我们不难发现,会TLE
所以快速幂就应用而生
算法思想
对数学敏感的盆友就会想到:
a
b
=
(
a
2
)
b
2
a^{b}=\left(a^{2}\right)^{\frac{b}{2}}
ab=(a2)2b
b
{b}
b变成
b
2
\frac{b}{2}
2b了,数据规模减小了耶
所以我们可以用循环直接重复此过程
#define ll long long
ll fastPower(ll a,ll b,ll p){
while(b>0){
a*=a; //乘幂
a%=p; // 取余,防止爆ll
b/=2; // 减少数据规模
}
return a;
}
但我们很快又发现了问题
在
b
{b}
b变成
b
2
\frac{b}{2}
2b时,数学中没啥毛病
but,在c++中,会直接向下取整,这样就会丢精度
所以,当为奇数时,还要做一些事情,不让他丢精度
我们不妨用一个ans变量存储一下结果
再加上之前的代码
#define ll long long
ll fastPower(ll a,ll b,ll p){
ll ans=1;
while(b>0){
if(b%2){ // 若为奇数
ans*=x; // 存储精度丢失部分
ans%=p;
}
a*=a; //乘幂
a%=p; // 取余,防止爆ll
b/=2; // 减少数据规模
}
return ans;
}
a,b,ans的变化如下表所示
a | b | ans |
---|---|---|
2 | 10 | 1 |
2 2 = 4 2^{2}=4 22=4 | 5 | 1 |
4 2 = 16 4^{2}=16 42=16 | 1 | 4 |
1 6 2 = 256 16^{2}=256 162=256 | 1 | 4 |
25 6 2 256^{2} 2562 | 0 | 4 ⋅ 1 6 2 = 1024 4\cdot16^{2}=1024 4⋅162=1024 |
(例:计算 2 10 2^{10} 210)
如果我们在think,think
就可以把他简化成究极无敌简洁的形式:
#define ll long long
ll fastPower(ll a,ll b,ll res,ll p){
if(y==0) return res;
else if (!y%2) return fastPower(a*a%p,y/2,res,p);
return fasePower(a*a%p,b/2,res*x%p,p);
}