2019ICPC南京网络赛B super_log
题意:求a的a的a次方。。一直求b次,也就是在纸上写个a,然后一直a次方a次方,对m取模,记为F(a,b,m)=pow(a,F(a,b-1,phi(m))
解题思路:联系欧拉降幂,这个迭代的过程,我们是一直对m求欧拉函数,然后在对这个结果求欧拉函数,显然这个过程迭代次数不会多,验证可得1e6范围内最多迭代19次,
但是这个题有个坑,快速幂必须取mod后+mod,才不会出现结果为0的情况,为0会导致有些情况不对(wa)
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+5; typedef long long ll; bitset<maxn>notprime; int phi[maxn],prime[maxn],cnt=0; void pre(){ phi[1]=1; for(int i=2;i<=maxn-5;i++){ if(!notprime[i]){ prime[++cnt]=i; phi[i]=i-1;//i为素数时,phi[i]=i-1 } for(int j=1;j<=cnt&&prime[j]*i<=maxn;j++){ notprime[i*prime[j]]=1; if(i%prime[j]==0){//每个数只被它的最小质因数给筛掉 phi[i*prime[j]]=phi[i]*prime[j]; //当a与b互质时,满足phi(a∗b)=phi(a)∗phi(b),积性函数 break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); //phi[i∗prime[j]]=phi[i]∗phi[prime[j]]=phi[i]∗(prime[j]−1); } } } ll quick_mod(ll a,ll n,ll mod) { ll res=1; while (n) { if(n&1)res=res*a>mod?res*a%mod+mod:res*a; a=a*a>mod?a*a%mod+mod:a*a; n>>=1; } return res; } ll deal(ll a,ll b,ll m) { if(b==0)return 1; if(m==1)return 1; ll res=deal(a,b-1,phi[m]); return quick_mod(a,res,m); } int main(){ pre(); int t; cin>>t; ll a,b,m; while (t--) { cin>>a>>b>>m; cout<<deal(a,b,m)%m<<endl; } }