题目大意:给出
p,a,b,X1
,有递推式
Xi+1=(aXi+b)%p
求
Xi=t
的最小的
i
,无解输出
题解:大力特判
1.X1=t
2.a=0
,即
Xi=b
3.a=1
,exgcd解同余方程,此时要特判b=0及同余方程无解
4.a≥2
展开递推式,得到
Xn+1=anX1+an−1b+an−2b+...+b
用一下等比数列求和公式,设
d=ba−1
,变成
Xn+1=anX1+and−d
整理一下,就是
an(X1+d)%p=t+d
这样就可以用bsgs解出n的最小值,注意要求的是n+1所以要答案+1
我的收获:数论大力特判!
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int kase;
ll P,A,B,X1,T;
ll qpow(ll a,ll b)
{
a%=P;ll c=1;
for(;b;b>>=1,a=a*a%P)
if(b&1) c=c*a%P;
return c;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b) d=a,x=1,y=0;
else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
ll inv(ll x){if(__gcd(x,P)!=1) return -1;return qpow(x,P-2);}
ll bsgs(ll a,ll b)
{
ll m,v,e=1;
m=ceil(sqrt(P));
v=inv(qpow(a,m));
if(v==-1) return -1;
map<ll,ll> S;S[1]=0;
for(int i=1;i<m;i++){
e=e*a%P;
if(!S.count(e)) S[e]=i;
}
for(int i=0;i<m;i++){
if(S.count(b)) return i*m+S[b]+1;
b=b*v%P;
}
return -1;
}
void work()
{
scanf("%lld%lld%lld%lld%lld",&P,&A,&B,&X1,&T);
if(X1==T){puts("1");return ;}
if(!A) puts(B==T?"2":"-1");
if(A==1){
if(!B){puts("-1");return ;}
ll G,X,Y;
ll C=(T-X1+P)%P;
exgcd(B,P,G,X,Y);
if(C%G){puts("-1");return ;}C/=G;
ll _B=P/G;
X=X*C%_B;
while(X<0) X+=_B;
printf("%lld\n",X+1);
}
if(A>1){
B=B*inv(A-1)%P;
X1=inv(X1+B);
T=(T+B)%P;
ll last=T*X1%P;
printf("%lld\n",bsgs(A,last));
}
}
int main()
{
scanf("%d",&kase);
while(kase--) work();
return 0;
}