[SDOI2013]随机数生成器

    \[X_{i+1} \equiv a*X_{i}+b\ (mod\  p)\]

    \[给出a,b,X_1,求满足X_{i} = t的最小i\]

这道题也是一道BSGS。

 不难推出

    \[X_{i+1} +\frac{b}{a-1} \equiv a*(X_{i}+\frac{b}{a-1})\ (mod\ p)\]

    \[X_{n} +\frac{b}{a-1} \equiv a^{n-1}*(X_1+\frac{b}{a-1})\ (mod\ p)\]

那么只要求满足

    \[a^x \equiv \frac{(a-1)t+b}{(a-1)X_1+b}\ (mod\ p)\]

的最小x即可,这一步可以使用BSGS解决。这道题还有一些特判,比较繁。代码如下:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long ll;
template<typename T> void read(T &x){
	x = 0;char ch = getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}
}
int mod,y,z,blc;
int mul(int a,int b){return 1ll*a*b%mod;}
int sq(int x){return 1ll*x*x%mod;}
int mpow(int a,int b){if(b == 0)return 1;return b&1?mul(a,sq(mpow(a,b/2))):sq(mpow(a,b/2));}
int inv(int x){return mpow(x,mod-2);}
int exgcd(int a,int b,int &x,int &y){
	if(b==0){x=1;y=0;return a;}
	int d=exgcd(b,a%b,y,x);y-=1ll*a/b*x;return d;
}
unordered_map<int,int> ump;
int main() {
	int TT,a,b,x1,t;
	read(TT);
	while(TT--){
		read(mod);read(a);read(b);read(x1);read(t);
		y = a%mod;
		if(x1 == t){cout<<"1\n";continue;}
		if(a==0){
			if(b==t)cout<<"2\n";
			else cout<<"-1\n";
			continue;
		}
		if(a == 1){
			int c = (t-x1+mod)%mod,x,y;
			int d = exgcd(b,mod,x,y);
			if(c%d!=0)cout<<"-1\n";
			else{
				x=1ll*x*c/d%mod;if(x<0)x+=mod;
				cout<<x+1<<endl;
			}
			continue;
		}
		z = mul(mul(a-1,t)+b,inv(mul(a-1,x1)+b));
		ump.clear();
		blc = sqrt(mod)+1;
		int cc = 1;
		for(int i=0;i<blc;i++){
			if(!ump.count(cc))ump[cc] = i;
			cc = mul(cc,y);
		}
		int st = 1,stinv = 1,invcc = inv(cc),fnd = 0;
		for(int po = 0;po<mod;po+=blc,stinv=mul(stinv,invcc)){
			if(!fnd && ump.count(mul(stinv,z)) && mpow(y,ump[mul(stinv,z)]+po) == z){
				cout<<ump[mul(stinv,z)]+po+1<<endl;
				fnd = 1;
			}
		}
		if(!fnd) cout<<"-1\n";
	}
	return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注