(T) 组数据,每次给定 (p),求
[left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod p ]
数据范围:(1le Tle 1000),(1le ple 10^7)。
这篇题解主要是给自己看的,因为小蒟蒻从未见过这种骚操作。
首先这个式子虽是无限的,但是答案是固定的。
- 先来几个引理
[a^{varphi(p)}equiv1pmod p
]
[a^bequiv a^{(bmod varphi(p))+varphi(p)}pmod p
]
所以上面那个递归式可以转化:
[2^{left(2^{left(2^{cdots}
ight)}
ight)}equiv 2^{left(2^{left(2^{cdots}
ight)}modvarphi(p)
ight)+varphi(p)}pmod p
]
所以可以先求 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod varphi(p)),又可以先求 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod varphi(varphi(p)))……最终一直递归下去。
[ecause
egin{cases}
varphi(1)=1\
varphi(p)<p&p>1\
end{cases}\
herefore varphi(varphi(varphi(cdotsvarphi(p)cdots)))=1\
]
因为 (left(2^{left(2^{left(2^{cdots} ight)} ight)} ight)mod 1=0),所以递归有边界了,可以开码了。
时间复杂度 (Theta({ m max}p+Tlog^2 p))。
- 代码:
#include <bits/stdc++.h>
using namespace std;
//Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x(a) a.first
#define y(a) a.second
#define b(a) a.begin()
#define e(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
//Data
const int N=1e7;
//Sieve
bitset<N+7> np;
int phi[N+7];
vector<int> pr;
void Sieve(){
np[1]=phi[1]=1;
for(int i=2;i<=N;i++){
if(!np[i]) pr.pb(i),phi[i]=i-1;
for(int p:pr)if(i*p<=N){
np[i*p]=1;
if(i%p==0){phi[i*p]=phi[i]*p;break;}
phi[i*p]=phi[i]*phi[p];
} else break;
}
}
//Pow
int Pow(int a,int x,int mod){
if(a==0) return 0; int res=1;
for(;x;a=1ll*a*a%mod,x>>=1)if(x&1) res=1ll*res*a%mod;
return res;
}
int Jump(int p){ // 两行核心代码
if(p==1) return 0;
return Pow(2,Jump(phi[p])+phi[p],p);
}
//Main
int main(){
int t; scanf("%d",&t);
Sieve();
for(int ti=1;ti<=t;ti++){
int p; scanf("%d",&p);
printf("%d
",Jump(p));
}
return 0;
}
祝大家学习愉快!