这题妙啊,我们做这道题遇到的首先一个门槛就是推式子:
[X_{i+1}=aX_{i}+b
]
我们考虑两边同时加上(frac{b}{a-1}),这样我们就构造出了一个等比数列:
[X_{i+1}+frac{b}{a-1}=a(X_i+frac{b}{a-1})(mod:p)
]
然后就是简单的等比数列求第(n)项:
[X_{n}+frac{b}{a-1}=a^{n-1}(X_1+frac{b}{a-1})(mod:p)
]
上式只有(n)是未知的,我们移项可得:
[a^{n-1}equiv(X_n+b*inv(a-1))*inv(X_1+b*inv(a-1))(mod:p)
]
我们求(n)就直接用bsgs就好了,注意明显的特殊数据就直接特判输出答案,看代码
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,C;
ll powmod(ll x,ll y,ll mod)
{
ll sum=1;
while(y)
{
if(y&1)
{
sum=sum*x%mod;
}
x=x*x%mod;
y>>=1;
}
return sum;
}
map<ll,ll> mp;
void bsgs(ll x,ll y,ll mod)
{
ll i,j;
if(x%mod==0)
{
printf("-1
");
return;
}
mp.clear();
ll m=sqrt(mod)+1,t,tt;
for(i=0,t=y;i<m;++i,t=t*x%mod) mp[t]=i;
for(i=1,tt=powmod(x,m,mod),t=tt;i<=m;i++,t=t*tt%mod)
{
j=mp.find(t)==mp.end()?-1:mp[t];
if(j>=0&&i*m-j>=0)
{
printf("%lld
",i*m-j+1);
return;
}
}
printf("-1
");
}
int main()
{
ll i,j,p,a,b,X1,t;
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&X1,&t);
if(X1==t){puts("1");continue;}
if(a==0){puts(t==b?"2":"-1");continue;}
if(a==1&&b==0){puts("-1");continue;}
if(a==1){
ll ny=powmod(b,p-2,p);
ll ans=((((t-X1)%p+p)%p)*ny%p)%p;
printf("%lld
",ans+1);continue;
}
ll u=b%p*powmod(a-1,p-2,p);
ll cc=(X1+u)%p;
C=(t+u)%p*powmod(cc,p-2,p)%p;
bsgs(a,C%p,p);
}
return 0;
}