[幂塔函数+欧拉降幂]2019ICPC南京网络赛B super_log

https://www.jisuanke.com/contest/3004?view=challenges
要求的东西可以变成b+loga*(logabx)>=b,即loga*(logabx)>=0
显然取等号最小
logabx=1是最小的满足loga*(logabx)=0的值,此时x也是最小的
所以取logabx=1
转换一下就变成了要求 x=aaa```,一共b个a

幂塔函数:aaa```
输入a,b,m,求b层的a幂塔函数的值%m
类似例题:BZOJ3884
https://blog.csdn.net/syh0313/article/details/88977745
https://blog.csdn.net/qq_37632935/article/details/81264965

#include
using namespace std;
typedef long long ll;
const int maxn=1e6+105;
ll T,primes[maxn],phi[maxn],cnt;
ll a,b,m,lim;
bool f[maxn];
ll tim[50];
ll po(ll a,ll b,ll mo){
    if(b==0) return 1%mo;
    if(b==1) return a%mo;
    ll c=po(a,b/2,mo);
    if (b&1) return c*c%mo*a%mo;else return c*c%mo;
}
ll solve2(ll d){
    if(d==0) return 1;
    return po(a,solve2(d-1),8e18);
}
ll solve(ll p,ll d){
    if (p==1) return 0;
    if(d==0) return 1%p;
    ll gcd=__gcd(a,p);//判断a,p是否互质
    if(gcd==1){//a,p互质,欧拉定理
        return po(a,solve(phi[p],d-1),p);
    }else{//扩展欧拉定理的范畴
        if(d<33&&tim[d-1]<phi[p]){//b
            return po(a,solve2(d-1),p);
        }else{
            return po(a,solve(phi[p],d-1)+phi[p],p);
        }
    }
}
ll check(ll a,ll b){//判断a^b有没有>1e6
    ll ans=1;
    while(b){
        if(b&1){
            ans*=a;
            if(ans>1e6) return 1;
        }
        b>>=1;
        if(!b) break;//必须要有这句
        a=a*a;
        if(a>1e6||ans*a>1e6) return 1;
    }
    return 0;
}
int main(){
    memset(f,1,sizeof(f));
    f[1]=0;
    phi[1]=1;
    for (int i=2;i<=1e6;i++){
        if (f[i]) primes[++cnt]=i,phi[i]=i-1;
        for (int j=1;j<=cnt && i*primes[j]<=1e6;j++){
            f[i*primes[j]]=0;
            if (i%primes[j]==0) {phi[i*primes[j]]=phi[i]*primes[j]; break;}
            else phi[i*primes[j]]=phi[i]*phi[primes[j]];
        }
    }
    scanf("%lld",&T);
    while (T--){
        memset(tim,127,sizeof(tim));
        scanf("%lld%lld%lld",&a,&b,&m);
        ll tmp=a;
        tim[0]=1;
        for(int i=1;i<32;i++){
            tim[i]=tmp;//i层的a幂塔的值
            if(check(a,tmp)){//如果下一层>1e6了,说明a^b中b>phi(p)
                lim=i;break;
            }
            tmp=po(a,tmp,(ll)8e18);
        }
        printf("%lld\n",solve(m,b));
    }
    return 0;
}

你可能感兴趣的:(数论,欧拉降幂)