「BZOJ 3122」「SDOI2013」 随机数生成器

Description

Description

Hint

(p in [2,10^9]) 且为质数。

保证 (X_1)(t) 都是合法的页码。

Solution

根据递推关系,得:

[X_2 equiv a cdot X_1 + b pmod p ]

[X_3 equiv a cdot X_2 + b equiv a^2 cdot X_1 + ab + b pmod p ]

[X_4 equiv a cdot X_3 + b equiv a^3 cdot X_1 + a^2b + ab + b pmod p ]

[cdots cdots ]

[X_n equiv a^{n-1} cdot X_1 + b imes sumlimits_{i=0}^{n-2} a^i pmod p ]

我们发现 (sum_{i=0}^{n-2} a^i) 就是一个等比数列求和,那么:

[X_n equiv a^{n-1} cdot X_1 + b imes dfrac{1 - a^{n-1}}{1 - a} pmod p ]

[X_n equiv a^{n-1} cdot X_1 - dfrac{a^{n-1}}{1 - a} + dfrac{b}{1 - a} pmod p ]

[X_n equiv a^{n-1} cdot (X_1 - dfrac{1}{1 - a}) + dfrac{b}{1 - a} pmod p ]

[a^{n-1} cdot (X_1 - dfrac{1}{1 - a}) equiv X_n - dfrac{b}{1 - a} pmod p ]

[a^{n-1} equiv dfrac{X_n - dfrac{b}{1 - a}}{X_1 - dfrac{1}{1 - a}} pmod p ]

而这个 (X_n) 其实就是题目中的 (t) ,那么我们就是要求关于 (n) 方程

[a^{n-1} equiv dfrac{t - dfrac{b}{1 - a}}{X_1 - dfrac{1}{1 - a}} pmod p ]

的这些非负整数解(如果有解的话)。

我们惊喜地发现这里只有 (n) 一个未知数,那么显然可以用 BSGS (这里 (p) 为质数)求解。

但这里还有不少需要注意的细节:

  • (t = X_1) 时,答案为 (0)
  • (a = 0) 时,(X_i equiv b pmod p),其中 (i > 1)
  • (a = 1) 时,(X_i equiv b(i-1) pmod p),那么这就是一个线性同余方程,直接求逆元即可。

注意式子中的所有除法都是逆元。

/*
 * Author : _Wallace_
 * Source : https://www.cnblogs.com/-Wallace-/
 * Problem : BZOJ 3122 SDOI2013 随机数生成器
 */
#include<cmath>
#include<iostream>
#include<tr1/unordered_map>

typedef long long LL;
typedef std::tr1::unordered_map<LL,LL> HashMap;
using std::cin;
using std::cout;
using std::endl;

LL fastpow(LL a,LL b,LL c) {
	if(!b) return 1ll%c;
	LL t=fastpow(a,b>>1,c);
	if(b&1) return t*t%c*a%c;
	else return t*t%c;
}

LL inverse(LL a,LL p) {
	return fastpow(a,p-2,p);
}

HashMap f;
inline LL BSGS(LL a,LL b,LL p) {
	f.clear();
	LL m=ceil(sqrt(p));
	b%=p;
	for(LL i=1;i<=m;i++)
		(b*=a)%=p,f[b]=i;
	LL t=fastpow(a,m,p);
	b=1;
	for(LL i=1;i<=m;i++) {
		(b*=t)%=p;
		if(f.count(b))
			return (i*m-f[b]+p)%p;
	}
	return -1;
}

signed main() {
	LL p,a,b,x1,t;
	int Test_c;
	cin>>Test_c;
	while(Test_c--) {
		cin>>p>>a>>b>>x1>>t;
		if(x1==t) {
			cout<<1<<endl;
		} else if(a==0) {
			if(b==t) cout<<2<<endl;
			else cout<<-1<<endl;
		} else if(a==1) {
			if(b==0) cout<<-1<<endl;
			else cout<<((t-x1)%p+p)%p*inverse(b,p)%p+1<<endl;
		} else {
			LL tmp=((b*inverse(a-1,p)%p+t)%p)%p*inverse((b*inverse(a-1,p)%p+x1)%p,p)%p;
			LL ans=BSGS(a,tmp,p);
			if(ans==-1) cout<<-1<<endl;
			else cout<<ans+1<<endl;
		}
	}
}
原文地址:https://www.cnblogs.com/-Wallace-/p/12608686.html