背景:
水博客系列。
题目传送门:
https://www.luogu.org/problem/P4139
题意:
求
2
2
2
2
2
2
.
.
,
m
o
d
  
p
2^{2^{2^{2^{2^2..,}}}}\mod p
222222..,modp。
这种形式是从上往下计算的。
思路:
遇到这种指数特别大的东西,我们就到考虑欧拉降幂。
由于指数是无穷的,因此我们认为
b
≥
ϕ
p
b≥\phi_p
b≥ϕp,我们只需要让
b
b
b每一次都取
b
m
o
d
  
ϕ
p
b\mod \phi_p
bmodϕp即可,可以
dfs
\text{dfs}
dfs实现。
边界是当
p
=
1
p=1
p=1时,
ϕ
p
=
1
,
b
m
o
d
  
ϕ
p
=
0
\phi_p=1,b\mod \phi_p=0
ϕp=1,bmodϕp=0。
预处理
ϕ
\phi
ϕ,再记忆化一下即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int p;
int phi[10000010],prime[10000010],f[10000010];
void init(int ma)
{
int t=0;
phi[1]=1;
for(int i=1;i<=ma;i++)
{
if(!phi[i]) phi[i]=i-1,prime[++t]=i;
for(int j=1;j<=t&&i*prime[j]<=ma;j++)
{
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
int ksm(int x,int k,int mod)
{
int tot=1;
for(;k;k>>=1)
{
if(k&1) tot=(LL)tot*x%mod;
x=(LL)x*x%mod;
}
return tot;
}
int dfs(int x)
{
if(x==1) return 0;
if(f[x]) return f[x];
return f[x]=ksm(2,dfs(phi[x])+phi[x],x);
}
int main()
{
int T;
init(10000000);
scanf("%d",&T);
while(T--)
{
scanf("%d",&p);
printf("%d\n",dfs(p));
}
}