超级快速幂
Time Limit: 3000/1000 MS(Java/Others) Memory Limit:65536/65536 K (Java/Others)
Description
请计算: a^(b^c)mod(1e9+7)
Input
多组数据,第一行为一个整数T,代表数据组数,接下来每行三个整数a,b,c(1<=a,b,c<=1,000,000,000)
Output
对于每组数据,输出一行代表计算结果
Sample Input
2
1 2 3
2 3 2
Sample Output
1
512
记得这是我们今年校赛的试题,当时直接暴力做,结果果断超时了,今天无意中想再看看,参考了两位大神的博客后,终于整理出来了。
快速幂模板1 :
利用公式a*b%c=((a%c)*b)%c
int modexp_simple(int a,int b,int n)
{
int ret = 1;
while (b--)
{
ret = a * ret % n;
}
return ret;
}
快速幂模板2:利用了二分的思想,可以达到O(logn).
(1)递归:
//计算a^bmodn
int modexp_recursion(int a,int b,int n)
{
int t = 1;
if (b == 0)
return 1;
if (b == 1)
return a%n;
t = modexp_recursion(a, b>>1, n);
t = t*t % n;
if (b&0x1)
{
t = t*a % n;
}
return t;
}
(2)非递归优化
#include <iostream>
using namespace std;
//计算a^bmodn
int modexp(int a,int b,int n)
{
int ret=1;
int tmp=a;
while(b)
{
//基数存在
if(b&0x1) ret=ret*tmp%n;
tmp=tmp*tmp%n;
b>>=1;
}
return ret;
}
int main()
{
cout<<modexp(2,10,3)<<endl;
return 0;
}
然后对于本题,还需要用到费马小定理 ,
当a和mod互质时,有 a^(mod-1) % mod = 1,所以a^(b^c)%mod=a^( b^c % (mod-1) ) %mod.
示例AC代码 :
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define LL long long
int modexp_recursion(int a,int b,int n)
{
int t = 1;
if (b == 0)
return 1;
if (b == 1)
return a%n;
t = modexp_recursion(a, b>>1, n);
t = t*t % n;
if (b&0x1)
{
t = t*a % n;
}
return t;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL a,b,c,n=1e9+7;
scanf("%d%d%d",&a,&b,&c);
LL s=modexp_recursion(b,c,n-1);
LL result=modexp_recursion(a,s,n);
printf("%lld\n",result);
}
return 0;
}