好神的一道欧拉函数。。
根据欧拉定理讲Mod展开为
2k
与j
这里
Mod=2k+j
然后加上欧拉定理就可以了
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
inline
int Pow(int A,int Pow,int Mod)
{
int res=1,Cur=A,j=1;
while(Pow)
{
if(j&Pow)res=Cur*1ll*res%Mod,Pow^=j;
Cur=Cur*1ll*Cur%Mod;j<<=1;
}
return res;
}
inline
int Calck(int C)
{
int l=C&-C;
if(l==1)return 0;
if(l==2)return 1;
if(l==4)return 2;
if(l==8)return 3;
if(l==16)return 4;
if(l==32)return 5;
if(l==64)return 6;
if(l==128)return 7;
l/=128;
if(l==2)return 8;
if(l==4)return 9;
if(l==8)return 10;
if(l==16)return 11;
if(l==32)return 12;
if(l==64)return 13;
if(l==128)return 14;
l/=128;
if(l==2)return 15;
if(l==4)return 16;
if(l==8)return 17;
if(l==16)return 18;
if(l==32)return 19;
if(l==64)return 20;
if(l==128)return 21;
l/=128;
if(l==2)return 22;
if(l==4)return 23;
if(l==8)return 24;
if(l==16)return 25;
if(l==32)return 26;
if(l==64)return 27;
if(l==128)return 28;
l/=128;
if(l==2)return 29;
if(l==4)return 30;
if(l==8)return 31;
if(l==16)return 32;
}
const
int Maxn=10001;
int Fai[Maxn];
int prime[Maxn];
bool Check[Maxn];
int F(int x)
{
if(x<Maxn)return Fai[x];
int res=1,t=sqrt(x),i;
for(i=1;prime[i]<=t;i++)
if(x%prime[i]==0)
{
res*=prime[i]-1;
x/=prime[i];
while(x%prime[i]==0)x/=prime[i],res*=prime[i];
if(x==1)break;
}
if(x!=1)
res*=x-1;
return res;
}
const
int INF=1<<29;
int DFS(int Mod)
{
if(Mod==1)return 0;
int k=Calck(Mod),j=Mod>>k,t=F(j);
int l=DFS(t);
l-=k;
l%=t;l+=t;l%=t;
l=Pow(2,l,j);
l%=j;
l*=Pow(2,k,INF);
return l;
}
int tot;
int main()
{
int i,j,k;
Fai[1]=1;
for(i=2;i<Maxn;i++)
{
if(!Check[i])prime[++tot]=i,Fai[i]=i-1;
for(j=1;j<=tot;j++)
{
k=prime[j]*i;
if(k>=Maxn)break;
Check[k]=true;
if(i%prime[j]==0){Fai[k]=prime[j]*Fai[i];break;}
Fai[k]=prime[j]*Fai[i]-Fai[i];
}
}
int T,p;
read(T);
while(T--)
{
read(p);
int Ans=DFS(p);
printf("%d\n",Ans);
}
return 0;
}