Problem
Solution
介绍一下扩展欧拉定理吧。
ab≡abmodϕ(p)+ϕ(p)
a
b
≡
a
b
mod
ϕ
(
p
)
+
ϕ
(
p
)
这个就可以解决b与p可能不互质的问题。
递归函数:
int solve(int p)
{
if(p==1) return 0;
reutrn power(2,solve(phi[p])+phi[p],p);
}
不过由于速度的原因,你可能会需要 O(logn) O ( l o g n ) 快速乘
int mul(int x,int y,int p)
{
int res=0;
while(y)
{
if(y&1) res=((ll)res+a)%p;
a=((ll)a+a)%p;
y>>=1;
}
return res;
}
不过,时间复杂度还可以更优啊,下面的方法参考了出题人大爷(PoPoQQQ)的题解:
注意到b的质因数只有2,那么将p中所有的2消去即可使其互质。
设
p=2k∗q,2∤q
p
=
2
k
∗
q
,
2
∤
q
根据同余的同乘性:
ans=2k∗(2(b−k)modϕ(q)modq)=2k∗(2(bmodϕ(q)−kmodϕ(q)+ϕ(q))modphi(q)modϕ(q)
a
n
s
=
2
k
∗
(
2
(
b
−
k
)
mod
ϕ
(
q
)
mod
q
)
=
2
k
∗
(
2
(
b
mod
ϕ
(
q
)
−
k
mod
ϕ
(
q
)
+
ϕ
(
q
)
)
mod
p
h
i
(
q
)
mod
ϕ
(
q
)
对于上面的 bmodϕ(q) b mod ϕ ( q ) 和原来求解的式子相同,那么就可以继续递归求解,边界条件p=1时返回0。
Code
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int z,a;
int phi(int x)
{
int i,res=x;
for(int i=2;i*i<=x;i++)
if(x%i==0)
{
res/=i;res*=i-1;
while(x%i==0) x/=i;
}
if(x^1) res/=x,res*=x-1;
return res;
}
int power(int x,int y,int p)
{
int res=1;
while(y)
{
if(y&1) res=(ll)res*x%p;
x=(ll)x*x%p;
y>>=1;
}
return res;
}
int solve(int x)
{
if(x==1) return 0;
int tmp=0;
while(~x&1) x>>=1,tmp++;
int p=phi(x);
int res=solve(p);
res+=p-tmp%p;res%=p;
res=power(2,res,x)%x;
return res<<tmp;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
scanf("%d",&z);
while(z--)
{
scanf("%d",&a);
printf("%d\n",solve(a));
}
return 0;
}