分析:
谁是欧拉?什么是扩展欧拉定理?
简单说一下:
如果给出的模数是奇数(一定和2互质),我们就可以用
(1)
(
1
)
把2的指数%
ϕ(p)
ϕ
(
p
)
,而对于指数的指数%
ϕ(ϕ(p))
ϕ
(
ϕ
(
p
)
)
,以此类推
2222... (mod p)=2(222...)mod ϕ(p) (mod p)=2(2(22...) mod ϕ(ϕ(p)))mod ϕ(p) (mod p)=... 2 2 2 2 . . . ( m o d p ) = 2 ( 2 2 2 . . . ) m o d ϕ ( p ) ( m o d p ) = 2 ( 2 ( 2 2 . . . ) m o d ϕ ( ϕ ( p ) ) ) m o d ϕ ( p ) ( m o d p ) = . . .
然而,由于 ϕ(ϕ(p))<p2 ϕ ( ϕ ( p ) ) < p 2 ,所以 ϕ(p) ϕ ( p ) 在 O(logn) O ( l o g n ) 次嵌套后就会变成1,等到 phi(p)=1 p h i ( p ) = 1 ,再往上就没有必要了(mod 1=0)
ϕ(ϕ(p))<p2 ϕ ( ϕ ( p ) ) < p 2
如果 p p 为奇数,那么最坏情况等于 p−1 p − 1 (质数),那么 phi(p) p h i ( p ) 一定是一个偶数
偶数的 ϕ ϕ 至多是(偶数不会与偶数互质),因此 ϕ(ϕ(p))<p2 ϕ ( ϕ ( p ) ) < p 2
如果 p p 为偶数,偶数的至多是 12 1 2 ,因此 ϕ(ϕ(p))<p2 ϕ ( ϕ ( p ) ) < p 2
然而如果p和2不互质,我们就不能把指数简单的
%ϕ(p)
%
ϕ
(
p
)
了
由欧拉定理的
(2)(3)
(
2
)
(
3
)
可以找到解决方法
然而欧拉定理只影响取模方式,不影响模数
重新定义一个mod运算即可
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
const int N=100010;
ll p,mod[N];
int cnt=0;
ll phi(ll a) {
ll b=a;
for (ll i=2;i*i<=a;i++)
if (a%i==0) {
b=b/i*(i-1);
while (a%i==0) a/=i;
}
if (a!=1) b=b/a*(a-1);
return b;
}
ll MOD(ll a,ll b) {
if (a<b) return a; //小于模数
else return a%b+b;
}
ll KSM(ll a,ll b,ll p) {
ll t=1;
while (b) {
if (b&1) t=MOD(t*a,p);
b>>=1;
a=MOD(a*a,p);
}
return t;
}
ll solve(int dep) {
if (dep>=cnt) return 1;
ll pp=solve(dep+1);
ll ans=KSM(2,pp,mod[dep]);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while (T--) {
scanf("%lld",&p);
cnt=0;
mod[++cnt]=p;
while (mod[cnt]!=1) mod[++cnt]=phi(mod[cnt-1]); //嵌套phi
printf("%lld\n",solve(1)%p);
}
return 0;
}