BZOJ 3122: [Sdoi2013]随机数生成器【BSGS】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88964816

题目传送门

题目分析:

大力推式子。注意推的时候要明确求的是什么。。
推式子的过程看这里
最后就是
a n 1 t ( a 1 ) + b x 1 ( a 1 ) + b   ( m o d   p ) a^{n-1}\equiv \frac {t(a-1)+b}{x_1(a-1)+b}~(mod~p)
要求n,BSGS即可。
注意几个特判:

  • x1==t puts(“1”);
  • a==0 puts(b==t?“2”:"-1");
  • a==1     t x 1 = b ( n 1 ) ~~~t-x_1=b(n-1) if(b==0) puts("-1"); else exgcd;

Code:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
inline int ksm(int a,int b,int p){
	int s=1;
	for(;b;b>>=1,a=1ll*a*a%p) if(b&1) s=1ll*s*a%p;
	return s;
}
void exgcd(int a,int b,int &x,int &y){
	if(!b) x=1,y=0;
	else exgcd(b,a%b,y,x),y-=a/b*x;
}
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
int BSGS(int a,int b,int p){
	if(b==1) return 0;
	static map<int,int>has; has.clear();
	int m=int(sqrt(p)+1),base=b,t=1;
	for(int i=0;i<m;i++) has[base]=i,base=1ll*base*a%p;
	base=ksm(a,m,p);
	for(int i=1;i<=m;i++) if(has.count(t=1ll*t*base%p)) return i*m-has[t];
	return -1;
}
int main()
{
	int T,a,b,X,t,p,x,y;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d%d%d",&p,&a,&b,&X,&t);
		if(X==t) puts("1");
		else if(a==0) puts(b==t?"2":"-1");
		else if(a==1) {if(!b) puts("-1");else exgcd(b,p,x,y),printf("%d\n",(1ll*x*(t-X)%p+p)%p+1);}
		else x=BSGS(a,(1ll*t*(a-1)+b)%p*ksm((1ll*(a-1)*X+b)%p,p-2,p)%p,p),printf("%d\n",x==-1?-1:x+1);
	}
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88964816
今日推荐