这题的想法好棒啊,原来欧拉函数还可以这么用的。(涨姿势.jpg)
首先有一个前置知识:降幂公式。(好像又叫扩展欧拉定理什么的)
我们知道欧拉定理,若 (a,m)=1 , aϕm≡1 (mod m) ,然后欧拉定理有一个推论:若 m≥ϕp ,则 am≡a(m mod ϕp)+p (mod p) 。话说这个公式好像叫降幂公式什么的。
然后我们令
f(p)=222...mod p
,因为
222...
显然大于
ϕp
,那么:
f(p)=222...mod p=2((22...)mod ϕp)+ϕpmod p=2f(ϕp)+pmod p
于是我们得到了 f(p) 的递归式,然后就是复杂度计算,至于怎么计算的, 大佬传送门。
附上AC代码:
#include <cstdio>
#include <map>
using namespace std;
map <int,int> f;
int t,x;
inline int pow(int x,int y,int p){
int ret=1;
while (y){
if (y&1) ret=1ll*ret*x%p;
x=1ll*x*x%p,y>>=1;
}
return ret;
}
inline int phi(int x){
int ret=x;
for (int i=2; i*i<=x; ++i)
if (x%i==0){
ret-=ret/i;
while (x%i==0) x/=i;
}
if (x>1) ret-=ret/x;
return ret;
}
inline int calc(int x){
if (f.count(x)) return f[x];
int y=phi(x);
return f[x]=pow(2,calc(y)+y,x);
}
int main(void){
f[1]=0;
for (scanf("%d",&t); t; --t) scanf("%d",&x),printf("%d\n",calc(x));
return 0;
}