题意:对于线性递推式(X_{i+1}≡aX_i+b(mod p)),给定(p,a,b,X_1,t),求最小的(i)满足(X_i=t)或者判断无解.
分析:考虑对递推式子进行转化,
(X_{i}=aX_{i-1}+b=a(X_{i-2}+b)+b)
(=...=a^{i-1}X_1+b+ab+a^2b+...+a^{i-2}b)
(=a^{i-1}X_1+frac{b(a^{i-1}-1)}{a-1}=t)
式子中只有(a^{i-1})是未知量,而我们要求的就是(i),所以考虑把(a^{i-1})单独拎出来,得到(a^{i-1}≡frac{(a-1)t+b}{(a-1)X_1+b}(mod p))
所以就可以直接套BSGS了.但因为右边是个分式,所以需要特判几种情况.
1、若(X_1=t),分式的值为1,所以(i=1);
2、若(a=0),如果(b=t),分式的值为0,所以(i=2),否则无解,输出(-1);
3、若(a=1),如果(b=0),分式无解,输出(-1),否则有式子(X_1+nb≡t(mod p)),直接求(t-X_1)乘b的逆元即可.
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
inline int ksm(int a,int b,int c){
int cnt=1;
while(b){
if(b&1)cnt=(1ll*cnt*a)%c;
a=(1ll*a*a)%c;
b>>=1;
}
return cnt;
}
map<int,int>ha;
inline int BSGS(int a,int b,int p){
if(a%p==0)return -2;
ha.clear();
int t=sqrt(p)+1,x=b,y=ksm(a,t,p);
for(int i=0;i<=t;i++){ha[x]=i;x=1ll*x*a%p;}
x=y;
for(int i=1;i<=t;i++){
if(ha.count(x))return i*t-ha[x];
x=1ll*x*y%p;
}
return -2;
}
int main(){
int T=read();
while(T--){
int p=read(),a=read(),b=read(),x1=read(),t=read();
if(x1==t){puts("1");continue;}
if(a==0){
if(b==t)puts("2");
else puts("-1");
continue;
}
if(a==1){
if(b==0)puts("-1");
else printf("%lld
",1ll*ksm(b,p-2,p)*(t-x1+p)%p+1);
continue;
}
int c=1ll*b*ksm(a-1,p-2,p)%p;
int d=1ll*(t+c)*ksm(x1+c,p-2,p)%p;
printf("%d
",BSGS(a,d,p)+1);
}
return 0;
}