Time Limit: 5 Sec
Memory Limit: 128 MB
Description
一句话题意:
2
2
2
…
 
m
o
d
 
p
2^{2^{2^{\dots}}}\bmod p
222…modp
Input
接下来T行,每行一个正整数p,代表你需要取模的值
Output
T行,每行一个正整数,为答案对p取模后的值
HINT
对于100%的数据,T<=1000,p<=10^7
题目分析
直到扩展欧拉定理的话其实就挺裸的
a
,
p
∈
Z
a,p\in Z
a,p∈Z,则
a
b
a^b
ab
{
a
b
,
b
<
φ
(
p
)
a
b
m
o
d
  
φ
(
p
)
+
φ
(
p
)
,
b
>
=
φ
(
p
)
\left\{\begin{aligned}a^b,b<\varphi(p)\\ a^{b\mod\varphi(p)+\varphi(p) },b>=\varphi(p)\end{aligned}\right.
{ab,b<φ(p)abmodφ(p)+φ(p),b>=φ(p)
m
o
d
  
p
\mod p
modp
因为指数
2
2
2
…
2^{2^{2^{\dots}}}
222…肯定大于
p
p
p,所以肯定适用下面这条
直接递归处理就好
#include<iostream>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=1e7;
int T;
lt p;
lt Phi(lt x)
{
lt res=x;
for(int i=2;i*i<=x;++i)
if(x%i==0){
res=res/i*(i-1);
while(x%i==0) x/=i;
}
if(x>1) res=res/x*(x-1);
return res;
}
lt qpow(lt a,lt k,lt mod)
{
lt res=1;
while(k>0){
if(k&1) res=(res*a)%mod;
a=(a*a)%mod; k>>=1;
}
return res;
}
lt solve(lt m)
{
if(m==1) return 0;
int phi=Phi(m);
return qpow(2,solve(phi)+phi,m);
}
int main()
{
Phi(maxn);
T=read();
while(T--)
{
lt p=read();
printf("%lld\n",solve(p));
}
return 0;
}