Description
在学了bsgs之后,我怎么觉得这题的难点是在于怎么求线性同余方程了...在这写一下顺便就当复习一下好了。
线性同余方程大概就是求解 ax=y (mod m) 的x,直观来看好像求个a的逆元乘个y就行了,但是事实上这个方程存在无解的情况,令d=gcd(a,m),如果y不能整除d方程是无解的,否则给y除以d,按上面的方法计算即可。
这道题怎么推导...不太会用latex就先不写了,黄学长写的挺清楚的,跳转。
话说就是bsgs这个根号暴力也好妙啊。
下附AC代码。
// luogu-judger-enable-o2
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#define maxn 100005
using namespace std;
typedef long long ll;
ll a,b,x1,t,mod;
ll exgcd(ll p,ll q,ll &x,ll &y)
{
if(!q)
{
x=1;
y=0;
return p;
}
ll temp=exgcd(q,p%q,y,x);
y-=(p/q)*x;
return temp;
}
ll quickpow(ll p,ll k)
{
ll ans=1;
while(k)
{
if(k&1)
ans=(ans*p)%mod;
p=(p*p)%mod;
k>>=1;
}
return ans;
}
map<ll,int> dic;
ll bsgs(ll x,ll y)
{
// cerr<<x<<" "<<y<<endl;
x%=mod;
if(!x)
{
if(!y) return 1;
return -1;
}
// cerr<<"+1"<<endl;
ll m=sqrt(mod)+1;
dic.clear(); dic[1]=m+1;
ll temp=1,temp2=quickpow(a,mod-1-m);
for(int i=1;i<m;i++)
{
temp=(temp*x)%mod;
if(!dic[temp])
dic[temp]=i;
}
temp=1;
for(int k=0;k<m;k++,temp=(temp*temp2)%mod)
{
int now=dic[y*temp%mod];
// cerr<<now<<endl;
if(now)
{
if(now==m+1) now=0;
return 1ll*k*m+now;
}
}
return -1;
}
ll solve1()
{
ll x,y;
ll temp1=exgcd(b,mod,x,y); x=(x%mod+mod)%mod;
ll temp2=(t-x1+mod)%mod;
if(temp2%temp1) return -1;
temp2/=temp1;
x=(x*temp2)%mod;
return x+1;
}
ll solve2()
{
ll c=quickpow(a-1,mod-2);
ll temp1=(b*c+x1)%mod;
ll temp2=(b*c+t)%mod;
ll x,y;
ll temp3=exgcd(temp1,mod,x,y); x=(x%mod+mod)%mod;
if(temp2%temp3) return -1; temp2/=temp3;
x=(x*temp2)%mod;
ll res=bsgs(a,x);
return res!=-1 ? res+1 : res;
}
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
scanf("%lld%lld%lld%lld%lld",&mod,&a,&b,&x1,&t);
if(x1==t) printf("%d\n",1);
else if(a==0)
{
if(b==t)
printf("%d\n",2);
else
printf("%d\n",-1);
}
else if(a==1)
{
printf("%lld\n",solve1());
}
else
{
printf("%lld\n",solve2());
}
}
}