BZOJ3122: [Sdoi2013]随机数生成器【BSGS】
3122: [Sdoi2013]随机数生成器
【题目描述】
【题解】
我们对于题目中的式子变换一下形式,
然后解出
套上等比数列公式
令为的逆元
求出后,BSGS求出n就可以了.
【代码如下】
#include<map>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long LL;
LL MOD,m,sp,c,x1,A,B,T,an;
map<LL,LL> hsh;
LL qsm(LL x,LL b){
LL Mul=1;x%=MOD;
for(;b;b>>=1,x=x*x%MOD) if(b&1) Mul=Mul*x%MOD;
return Mul;
}
LL BSGS(LL a,LL t){
hsh.clear();hsh[t]=0;
for(LL i=1,x=a;i<=m;i++,x=x*a%MOD) if(!hsh[x*t%MOD]) hsh[x*t%MOD]=i;
for(LL i=1,p=qsm(a,m),x=p;i<=m;i++,x=x*p%MOD) if(hsh[x]) return i*m-hsh[x];
return -2;
}
void solve(){
c=qsm(A-1,MOD-2);m=ceil(sqrt(MOD));
an=(T+B*c%MOD)%MOD*qsm(x1+B*c%MOD,MOD-2)%MOD;
printf("%lld\n",BSGS(A,an)+1);
}
int main(){
int TT;scanf("%lld",&TT);
while(TT--){
scanf("%lld%lld%lld%lld%lld",&MOD,&A,&B,&x1,&T);
if(T==x1){printf("1\n");continue;}
if(A==0){if(T==B) printf("2\n");else printf("-1\n");continue;}
if(A==1&&B==0){printf("-1\n");continue;}
if(A==1){
LL Ans=((T-x1)%MOD+MOD)%MOD*qsm(B,MOD-2)%MOD;
printf("%lld\n",Ans+1);continue;
}
solve();
}
return 0;
}