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\n",1ll*((xn-x1)%p+p)%p*qpow(b,p-2)%p+1);
			continue;
		} printf("%d\n",BSGS()+1);
	}
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.24
76

posted @ 2019-08-24 14:44  LuitaryiJack  阅读(222)  评论(0编辑  收藏  举报