BZOJ3122: [Sdoi2013]随机数生成器【BSGS】

3122: [Sdoi2013]随机数生成器

【题目描述】

传送门

【题解】

我们对于题目中的式子变换一下形式,Xi+1+k=a(Xi+k)X_{i+1}+k=a(X_i+k)Xi+1+k=a(Xi+k)

然后解出k=ba−1k=\frac{b}{a-1}k=a1b

套上等比数列公式Xn=X1an−1+b(an−1−1)a−1\large X_n=X_1a^{n-1}+\frac{b(a^{n-1}-1)}{a-1}Xn=X1an1+a1b(an11)

ccca−1a-1a1的逆元

(X1+bc)an−1=t+bc(X1+bc)a^{n-1}=t+bc(X1+bc)an1=t+bc

求出an−1a^{n-1}an1后,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;
}

转载于:https://www.cnblogs.com/XSamsara/p/10547926.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值