题目大意
输入A,M,找任意一个K ,使得 AK≡K(mod M)
题解
欧拉定理
若n,a互质,则
证明:
令1~n中,与n互质的数为
x1,x2,x3,...,xϕ(n)
令
mi=axi
,
- 性质1:所有
mi
中,任意两个都不关于n同余。
若存在 mi≡mj(mod n)
则 n|mi−mj , n|a(xi−xj) ,∵n与a互质, xi−xj<n , n 不整除a(xi−xj) ,矛盾。 - 性质2:所有
mi mod n
与n互质。
令 mi=pn+r ,若r与n有公因子q,则 mi 也一定有因子q, mi 与 n 不互质
∵a与n互质,x_i与n互质,axi 不含n的任何因子,矛盾。
由以上性质得出
m1,m2,m3,...,mϕ(n)
所有数模n,得到的数一定是
x1,x2,x3,...,xϕ(n)
∴
m1m2m3...mϕ(n)≡x1x2x3...xϕ(n)(mod n)
(aϕ(n)−1)x1x2x3..xϕ(n)≡0(mod n)
n|(aϕ(n)−1)x1x2x3..xϕ(n)
n|aϕ(n)−1
aϕ(n)≡1(mod n)
缩小问题规模
AK≡K(mod M)
Aϕ(M)...Aϕ(M)AK mod ϕ(M)≡K(mod M)
∵
Aϕ(M)≡1(mod M)
∴
AK mod ϕ(M)≡K(mod M)
找一个t,使得
t≡K(mod ϕ(M))
∴
At≡AK≡K(mod M)
At mod M=t mod ϕ(M)
∴
At≡t(mod gcd(M,ϕ(M)))
然后问题变为求t,M缩小。
具体实现
当M=1时,K=1。
用
O(M−−√)
暴力求出
ϕ(M)
,取
gcd(M,ϕ(M))
递归求解,得到一个t.
根据以下条件
At≡K(mod M)
At mod M=t mod ϕ(M)=K
得出
x×M+At mod M=y×ϕ(M)+t mod ϕ(M)
x×M−y×ϕ(M)=t mod ϕ(M)−At mod M
可用扩展欧几里得解出这个不定方程的x.
为保证得到正数,适当的把t扩大,加上几个
ϕ(M)
使等式右边变为正数.
解出x后
K=x×M+At mod M
代码
#include<cstdio>
long long modpow(long long a,long long b,long long p)
{
long long ret=1;
for(;b>0;b>>=1,a=(a*a)%p)
if(b&1)
ret=(ret*a)%p;
return ret;
}
long long phi(long long n)
{
long long res=n,t=n;
for(long long i=2;i*i<=t;i++)
if(t%i==0)
{
res-=res/i;
while(t%i==0)
t/=i;
}
if(t>1)
res-=res/t;
return res;
}
long long gcd(long long a,long long b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if(b==0)
{x=1;y=0;return a;}
long long g;
g=exgcd(b,a%b,y,x);
y-=a/b*x;
return g;
}
long long solve(long long A,long long M)
{
if(M==1)
return 1;
long long pM,At,d,t,x,y;
pM=phi(M);
d=gcd(M,pM);
t=solve(A,d);
At=modpow(A,t,M);
exgcd(M/d,pM/d,x,y);
x=x*(((t-At)%pM+pM)%pM)/d;
x=((x%(pM/d))+pM/d)%(pM/d)+pM/d;
return x*M+At;
}
int main()
{
int Q;
long long A,M;
scanf("%d",&Q);
while(Q--)
{
scanf("%lld%lld",&A,&M);
printf("%lld\n",solve(A,M));
}
return 0;
}