3211. 【SDOI2013】随机数生成器

Description

小 W喜欢读 书,尤其喜欢读 书,尤其喜欢读《约翰克里斯 朵夫》。 最近小 W准备读一本新书,这本一共有 p页, 页码范围为 0..p -1。

小 W很忙,所以每天只能读一页书  。为了使事情有趣一些 ,他打算使用 NOI2012上学习的线性同余法生成 一个序列 ,来决定每天具体读哪一页 。

我们用 Xi来表示通过这种方法生成出来第 i个数 ,也即小 W第 i天会读 哪一页 。这个方法 需要设置 3个参数 a,b,X1,满足 0≤a,b,X1≤p-1,且 a, b,X1都是整数 。按照下面的公式 按照下面的公式生成出来一系列的 整数。

Xi+1= (aXi + b) mod p

其中 mod p 表示前面的数除以 p的余数。

可以发现,这个序列中下一个数总是由上一个数生成的 ,而且每一项都在 0..p -1这个范围内 ,是一个合法的页码。 同时需要注意 ,这种方法有可能导致某两天读的页码完全一样 。

小 W非常急切 地想去读这本书的第t页。所以他想知道, 对于一组给定的 a, b,X1,如果使用线性同余法来生成每一天读的页码, 最早读到第t页是在哪一天,或者指出他永远不会读到第t页。

Input

输入含有多组数据 ,第一行一个正整数T,表示这个测试点内的数据组数。

接下来 T行,每行有 五个整数 p,a,b,X1,t,表示一组数据。 保证 X1和 t都是合法的页码。

Output

共 T行,每行一个整数表示他最早读到第t页是哪一天 。如果他永远不会读到第t页,输出 -1。

Sample Input

3

7 1 1 3 3

7 2 2 2 0

7 2 2 2 1

Sample Output

1

3

-1

Data Constraint

Hint

对于第一组数据,生成的序列为: 3,4,5,6,0…

对于第二 、三 组数据, 生成的序列为: 2,6,0,2…

Solution

BSGS

x_{n+1}=ax_n+b

x_{n+1}=a(ax_{n-1}+b)+b

x_{n+1}=a^2x_{n-1}+ab+b

...

x_{n+1}=a^nx_1+a^{n-1}b+a^{n-2}b+...+ab+b

套等差数列公式

x_{n+1}=a^nx_1+\frac{b(a^n-1)}{a-1}

x_{n+1}+\frac{b}{a-1}=a^nx_1+\frac{a^nb}{a-1}

x_{n+1}+\frac{b}{a-1}=a^n(x_1+\frac{b}{a-1})

\frac{x_{n+1}+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}=a^n

现在已知x的第n+1项为t(即x_{n+1}=t),求n+1的最小值

a^n=\frac{t+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}

a^n\equiv \frac{t+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}(mod ~p)

a^n\equiv \frac{t(a-1)+b}{x_1(a-1)+b}(mod ~p)

对于分母求逆元,对于整个式子BSGS

总结:注意同一个变量不能多用,多开几个变量就好了。同时对于每个相同或相似的过程最好统一一下变量名。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define M 70921
using namespace std;
I T,p,a,b,x,t,m,now,ans,inf=0x7fffffff;
struct node{I v,c;}h[M+10];
void R(I &x){
	I w=1;x=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	x*=w;
}
I ksm(ll x,I k){
	ll sum=1;
	while(k){
		if(k&1) sum=(sum*x)%p;
		x=(x*x)%p;k>>=1;
	}
	return sum;
}
I hash(I x){
	I k=x%M;
	while(h[k].v>=0&&h[k].v!=x) if(++k==M) k=0;
	return k;
}
I main(){
	freopen("generator.in","r",stdin);
	freopen("generator.out","w",stdout);
	R(T);
	while(T--){
		ans=inf;
		R(p),R(a),R(b),R(x),R(t);
		if(x==t){printf("1\n");continue;}
		if(x==0&&b==0){printf("-1\n");continue;}
		if(a==0){printf(b==t?"2\n":"-1\n");continue;}
		if(a==1){
			if(!b){printf("-1\n");continue;}
			now=(ll)(t-x+p)%p*ksm(b,p-2)%p;
			printf("%d\n",now+1);continue;
		}
		memset(h,255,sizeof h);
		t=((1LL*t*a-t+b)%p+p)%p*ksm(((1LL*x*a-x+b)%p+p)%p,p-2)%p;
		m=sqrt(p);
		F(j,1,m){
			x=hash(t=1LL*t*a%p);
			h[x]=node{t,j};
		}
		now=ksm(a,m);x=1;
		F(i,1,m+1){
			t=hash(x=1LL*x*now%p);
			if(h[t].c>=0) ans=min(ans,i*m-h[t].c+1);
		}		
		printf((ans==inf)?"-1\n":"%d\n",ans);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/107772896