题目传送门
题解
这道题其实就是一个欧拉函数的性质的应用:
若
(a,m)=1
(
a
,
m
)
=
1
且
a,m≥2
a
,
m
≥
2
,则
aφ(m) mod m≡1
a
φ
(
m
)
m
o
d
m
≡
1
。
我们设
x=222...
x
=
2
2
2
.
.
.
,
p=2kq
p
=
2
k
q
,
(q,2)=1
(
q
,
2
)
=
1
。
则
x mod p
x
m
o
d
p
=2k(2x−k mod q) mod p
=
2
k
(
2
x
−
k
m
o
d
q
)
m
o
d
p
=2k(2(x−k) mod φ(q)+φ(q) mod q) mod p
=
2
k
(
2
(
x
−
k
)
m
o
d
φ
(
q
)
+
φ
(
q
)
m
o
d
q
)
m
o
d
p
我们令
f(i,j)=(x−i) mod j
f
(
i
,
j
)
=
(
x
−
i
)
m
o
d
j
则
f(0,p)=2k(2f(k,φ(q))+φ(q) mod q) mod p
f
(
0
,
p
)
=
2
k
(
2
f
(
k
,
φ
(
q
)
)
+
φ
(
q
)
m
o
d
q
)
m
o
d
p
于是我们只需要递归计算即可。当
q=1
q
=
1
就返回
0
0
。
答案就是。
代码
#include<cstdio>
#define int long long
int t,p;
int calcphi(int n){
if(n==1||n==2){
return 1;
}
int res=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
res=res/i*(i-1);
while(n%i==0){
n/=i;
}
}
}
if(n!=1){
res=res/n*(n-1);
}
return res;
}
int fastpow(int a,int x){
int res=1;
while(x){
if(x&1){
res*=a;
}
x>>=1;
a*=a;
}
return res;
}
int fastpow2(int a,int x,int mod){
int res=1;
while(x){
if(x&1){
res=res*a%mod;
}
x>>=1;
a=a*a%mod;
}
return res;
}
int solve(int i,int j){
if(j==1){
return 0;
}
int u=0,tmp=j;
while(!(tmp&1)){
u++;
tmp>>=1;
}
int phi=calcphi(tmp);
return (fastpow(2,u)*(fastpow2(2,solve(u,phi)+phi,tmp)%tmp)%j-i%j+j)%j;
}
signed main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&p);
printf("%lld\n",solve(0,p));
}
return 0;
}