求a的b次方。(比如求 2^256 和2^16)
去求一些大数对于某个数的余数,为了得到更快、计算范围更大的算法,产生了快速幂取模算法。
普通算法:
LL qwe1(LL x,LL y){
LL res = 1;
for(LL i=1; i<=y; ++i)
res *= x;
return res;
}
复杂度: O(n)
求 2^256 会溢出, 求2^16要循环16次;
很显然,当a 和 b很大时就会溢出,而且有可能会超时
快速幂算法:
LL qwe2(LL x,LL y){
LL t = 1;
while(y){
if(y & 1)t = t * x % Mod;
y >>= 1;
x = x * x % Mod;
}
return t;
}
复杂度 : O(logn)
求 2^256的过程,循环只执行了9次;
2^256 == 4^(128) == 16^(64) == 256^(32) == 65536^16 == (256*256)^8 …… ==792845266;
求2^16的过程循环只执行了5次;
2^16 == 4^8 == 16^4 == 256^2 == 65536 ;
这个算法能在几乎所有的程序设计(竞赛)过程中通过,是目前最常用的算法之一。
代码的实现:
#include <bits/stdc++.h>
typedef long long LL;
const int MaxN = 1e5;
const int Mod = 1e9 + 7;
using namespace std;
LL a,b,cnt1 = 0,cnt2 = 0;
LL qwe1(LL x,LL y){
LL res = 1;
for(LL i=1; i<=y; ++i){
res *= x;
cnt1++;
}
return res;
}
LL qwe2(LL x,LL y){
LL t = 1;
while(y){
if(y & 1)t = t * x % Mod;
y >>= 1;
x = x * x % Mod;
cnt2++;
}
return t;
}
int main(){
cin>>a>>b;
cout<<qwe1(a,b)<<endl;
cout<<cnt1<<endl;
cout<<qwe2(a,b)<<endl;
cout<<cnt2<<endl;
return 0;
}