快速幂就是快速求解一个整数a的n次幂的算法,传统的求解思路是按照线性的求解顺序:(a^n = a*a*a*...*a),这样做的算法时间复杂度是(O(n)),而快速幂借助二进制的思想,可以将时间复杂度降低到(O(logn))
int quick_pow(int a, int n)
{
int ans = 1;
int tot = a;
while(n){
if(n&1) ans*=tot; // 如果这位上为1,那么ans就乘以当前的tot
tot*=tot; // tot自乘
n>>=1; // 相当于n/2
}
}
快速幂的算法很简单,也很好理解;
就是把n看成二进制的数,比如对于(a^{11}),((11)_{10} = (1011)_2),那么使用快速幂的求解过程如下:
- (ans=a, tot = a^2, n=(101)_2)
- (ans=a^3, tot=a^4, n=(10)_2)
- (ans=a^3, tot=a^8, n=(1)_2)
- (ans=a^11, tot=a^{16}, n=0)
这里本质上是使用二进制表示n的思想,因为任意一个十进制的整数都可以表示成二进制的数
时间复杂度由于tot是指数上升的,所以乘法的次数是(logn)
例题:洛谷p1226
ac代码:
#include<bits/stdc++.h>
typedef long long ll; // 要使用ll类型
using namespace std;
int q_pow(ll a, ll n, ll k)
{
ll ans = 1;
ll tot = a;
while(n){
if(n&1) ans = (ans*tot)%k;
tot = (tot*tot)%k; // 这里也要取余,but why?
n>>=1;
}
return ans%k; // 输出答案的时候不要忘记把最终的答案再对p取一次模,否则就会只有 84分。
}
int main()
{
ll b, p, k;
cin >> b >> p >> k;
printf("%lld^%lld mod %lld=%lld", b, p, k, q_pow(b, p, k));
return 0;
}
参考链接:
https://www.cnblogs.com/wty20010315/p/6984348.html