BZOJ3884: 上帝与集合的正确用法

时间:2022-09-05 23:18:41

题目大意:

求2^(2^(2^...))%p的值,每次给定p。

题解:

扩展欧拉定理

a^n=a^(a%phi(p)+phi(p)) (mod p)

设f(p)为模数为p时候这个式子的答案。

f(p)=2^(f(phi(p))+phi(p))

然后递归暴力,因为每次取phi,不会递归很多层

代码:

#include<cstdio>
using namespace std;
int cnt,isprime[10000005],prime[2000005],phi[10000005];
int pow(int a,int b,int mod){
	int ans=1;
	while (b){
		if (b&1) ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		b=b>>1;
	}
	return ans;
}
long long calc(int mod){
	if (mod==1) return 0;
	return pow(2,calc(phi[mod])+phi[mod],mod);
}
int main(){
	int t;
	scanf("%d",&t);
	for (int i=2; i<=10000000; i++){
		if (!isprime[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for (int j=1; j<=cnt && i*prime[j]<=10000000; j++){
			isprime[i*prime[j]]=1;
			if (i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
	while (t--){
		int mod;
		scanf("%d",&mod);
		printf("%d\n",calc(mod));
	}
	return 0;
}