1. 程式人生 > >擴充套件尤拉定理【洛谷P4139】 上帝與集合的正確用法

擴充套件尤拉定理【洛谷P4139】 上帝與集合的正確用法

P4139 上帝與集合的正確用法

\(2^{2^{2^{\dots}}}\bmod p\)

卡最優解倒數第一祭。

帶一下擴充套件尤拉定理就好了。

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

const int wx=10000017;

int isprime[wx],prime[wx],phi[wx];
int tot;

inline long long read(){
    long long sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

void Euler_phi(){
    memset(isprime,1,sizeof isprime);
    phi[1]=1; isprime[1]=0;
    for(int i=2;i<=10000000;i++){
        if(isprime[i]){
            prime[++tot]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=tot&&i*prime[j]<=10000000;j++){
            isprime[i*prime[j]]=0;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}

long long ksm(long long a,long long b,long long mod){
    long long re=1;
    while(b){
        if(b&1)re=re*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return re;
}

long long work(long long mod){
    if(mod==1)return 0;
    return ksm(2,work(phi[mod])+phi[mod],mod);
}

signed main(){
//  for(long long i=1;i<=430000000;i++);
    int T=read(); Euler_phi();
    while(T--){
        long long p=read();
        printf("%lld\n",work(p));
    }
    return 0;
}