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;
    }
}

猜你喜欢

转载自www.cnblogs.com/xusirui/p/11443214.html