[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 }

 

posted @ 2017-11-18 22:00  Elpsywk  阅读(205)  评论(0编辑  收藏  举报