[bzoj3884]上帝与集合的正确用法
题意:求${2^{{2^{{2^{...}}}}}}\bmod p$
解题关键:
因为${a^n} \equiv {a^{n\bmod \varphi (p) + \varphi (p)}}\bmod p,n > \varphi (p)$
所以,
$\begin{array}{l}
f(p) = {2^{{2^{{2^{...}}}}}}\bmod p = {2^{{2^{{2^{...}}}}\bmod \varphi (p) + \varphi (p)}}\bmod p\\
= {2^{f(\varphi (p)) + \varphi (p)}}\bmod p
\end{array}$
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<iostream> 6 #include<cmath> 7 using namespace std; 8 typedef long long ll; 9 const int MAXN=10000000+10; 10 int prime[MAXN];//保存素数 11 bool vis[MAXN];//初始化 12 int phi[MAXN];//欧拉函数 13 void Lphisieve(int n){ 14 int cnt=0; 15 for(int i=2;i<n;i++){ 16 if(!vis[i]){ 17 prime[cnt++]=i; 18 phi[i]=i-1; 19 } 20 for(int j=0;j<cnt&&i*prime[j]<n;j++){ 21 int k=i*prime[j]; 22 vis[k]=true; 23 if(i%prime[j]==0){ 24 phi[k]=phi[i]*prime[j]; 25 break; 26 } 27 else phi[k]=phi[i]*(prime[j]-1); 28 } 29 } 30 } 31 32 ll mod_pow(ll x,ll n,ll p){ 33 ll res=1; 34 while(n){ 35 if(n&1) res=res*x%p; 36 x=x*x%p; 37 n>>=1; 38 } 39 return res; 40 } 41 42 ll work(ll n){ 43 if(n==1) return 0; 44 return mod_pow(2,work(phi[n])+phi[n],n); 45 } 46 47 int main(){ 48 int T; 49 Lphisieve(10000001); 50 scanf("%d", &T); 51 while(T--){ 52 ll n; 53 scanf("%lld",&n); 54 printf("%lld\n",work(n)); 55 } 56 return 0; 57 }