题目链接
  https://www.lydsy.com/JudgeOnline/problem.php?id=3884
分析
  扩展欧拉定理裸题
- 欧拉定理及证明: - 如果$(a,m)=1$,则$a^{\phi(m)} \equiv 1 \mod m$ - $Prove:$设$x$取遍$m$的缩系,则$ax$取遍$m$的缩系,即 - 因为这样的$a$有$\phi(m)$个 - 由于$(x,m)=1$,保证$\prod x$ 存在模$m$意义下的逆元 - 所以  
- 扩展欧拉定理: - 如果 
 则
 - 设$f(x)$为在模$x$意义下题目式子的值,那么 - 然后就可以记忆化搞一搞了 
注意
  求欧拉函数可以线性预处理也可以直接求,实践证明直接求不知道快到哪里去了
代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 
 | #include <iostream>#include <cstdio>
 #include <cstdlib>
 #include <cstring>
 #include <algorithm>
 #include <cctype>
 #define ll long long
 #define ri register int
 using std::sort;
 template <class T>inline void read(T &x){
 x=0;int ne=0;char c;
 while(!isdigit(c=getchar()))ne=c=='-';
 x=c-48;
 while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
 x=ne?-x:x;return ;
 }
 const int maxn=10000005;
 const int inf=0x7fffffff;
 int t,n;
 int mem[maxn];
 int phi[maxn];
 bool vis[maxn];
 inline void get_table(){
 bool is_pri[maxn];
 int num[1000005],tot=0,tmp;
 memset(is_pri,0,sizeof(is_pri));
 is_pri[1]=1;
 phi[1]=1;
 for(ri i=2;i<=maxn;i++){
 //printf("%d\n",i);
 if(!is_pri[i]){
 num[++tot]=i;
 phi[i]=i-1;
 }
 for(ri j=1;j<=tot;j++){
 tmp=num[j]*i;
 if(tmp>=maxn)break;
 is_pri[tmp]=1;
 if(i%num[j]==0){
 phi[tmp]=num[j]*phi[i];
 break;
 }
 else {
 phi[tmp]=(num[j]-1)*phi[i];
 }
 }
 }
 return ;
 }
 inline int get_phi(int x){
 int res=x;
 for(ri i=2;i*i<=n;i++){
 if(x%i==0){
 res=res/i*(i-1);
 while(x%i==0)x=x/i;
 }
 }
 if(x>1)res=res/x*(x-1);
 return res;
 }
 int ksm(ll x,int c,int p){
 ll ans=1,res=x;
 while(c){
 if(c&1)ans=ans*res%p;
 res=res*res%p;
 c=c>>1;
 }
 return ans%p;
 }
 int f(int x){
 if(x==1)return 0;
 if(vis[x])return mem[x];
 int p=phi[x];//int p=get_phi(x);
 vis[x]=1;
 mem[x]=ksm(2,f(p)+p,x);
 return mem[x];
 }
 int main(){
 read(t);
 get_table();
 while(t--){
 read(n);
 printf("%d\n",f(n));
 }
 return 0;
 }
 
 |