P3306 [SDOI2013]随机数生成器

思路:(BSGS)

提交:(1)

题解:

原式可以化为$$x_{i+1}+frac{b}{a-1}=a(x_{i}+frac{b}{a-1})mod p$$
这不是等比数列吗?

[x_{n}+frac{b}{a-1}=a^{n-1}cdot (x_{1}+frac{b}{a-1})mod p ]

所以有

[a^{n-1}=(x_{1}+frac{b}{a-1})^{-1}cdot (x_{n}+frac{b}{a-1})mod p ]

这样我们可以(BSGS)
注意特判(a=1,0)的情况

#include<cstdio>
#include<iostream>
#include<unordered_map>
#include<cmath>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
}
int T,p,a,b,x1,xn;
inline ll qpow(ll a,ll b) { register ll ret=1;
	for(;b;b>>=1,(a*=a)%=p) if(b&1) (ret*=a)%=p; return ret;
}
inline int BSGS() {
	unordered_map<int,int> hsh; hsh.clear();
	R t=sqrt(p)+1; R c=(xn+1ll*b*qpow(a-1,p-2))%p*qpow((x1+1ll*b*qpow(a-1,p-2))%p,p-2)%p;
	for(R i=1;i<=t;++i) {
		R vl=1ll*c*qpow(a,i)%p;
		hsh[vl]=i;
	} a=qpow(a,t); 
	if(a==0) return c==0?1:-2;
	for(R i=1;i<=t;++i) {
		R vl=qpow(a,i);
		if(hsh.count(vl)&&i*t-hsh[vl]>=0) return i*t-hsh[vl];
	} return -2;
}
inline void main() {
	g(T); while(T--) {
		g(p),g(a),g(b),g(x1),g(xn);
		if(x1==xn) {puts("1"); continue;}
		if(a==0) {if(xn==b) puts("2"); else puts("-1"); continue;}
		if(a==1&&b==0) {puts("-1"); continue;}
		if(a==1) {
			printf("%d
",1ll*((xn-x1)%p+p)%p*qpow(b,p-2)%p+1);
			continue;
		} printf("%d
",BSGS()+1);
	}
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.24
76

原文地址:https://www.cnblogs.com/Jackpei/p/11404629.html