扩展欧拉定理【洛谷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;
}
posted @ 2018-11-06 20:59  _王小呆  阅读(196)  评论(0编辑  收藏  举报