欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2017.9.25 随机数生成器 失败总结

程序员文章站 2022-03-14 19:57:39
...

、这个题要用bsgs

如果知道bsgs的话化式子就很有方向了

首先把霍纳法则拆成数列

然后得到 x1*a^n + a^n-1 *b+ a^n-2 *b+.. a*b==t  (%P)

              用等比数列公式,得x1*a^n +b*(a-a^n)/(1-a)==t  (%P)

              然后就知道怎么做了、把a^n 放在一块      ((a-1)*x1+b)*a^n ==t*(a-1)+b(%P)


然后就是求这个式子最小的n值

其实bsgs就是分块、、设m=根P    n=m*i+j

  ((a-1)*x1+b)*a^(m*i+j)==t*(a-1)+b(%P)

  ((a-1)*x1+b)*a^(j)==(t*(a-1)+b )  *a^(-m*i )  (%P)

然后由于j 和 i都只有根n个取值,所以可以预处理每个j对应的值,再枚举i   判断即可

由于页数<P,所以直接取模放进map里就可以了,取模一样页数一定也一样



注意:只要空间不卡,一定要开long long!


码(1100ms卡过、):

#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
using namespace std;

#define ll long long
ll P,x,y,T,t,x1,a,b,xishu,m,i;
map<ll,ll>ma;
ll ksm(ll a,ll b)
{
	ll ans=1;
while(b)
{
if(b%2)ans=ans*a%P;
b/=2;
a=a*a%P;	
}	
	return ans;
}
void exgcd(ll a,ll b)
{
	if(!b)
	{
	x=1;
	y=0;	
	return;	
	}
	exgcd(b,a%b);
	ll t=x;
	x=y;
	y=t-(a/b)*y;
}
int main()
{
	scanf("%lld",&T);
	while(T--)
	{
		bool jieshu=0;
	scanf("%lld%lld%lld%lld%lld",&P,&a,&b,&x1,&t);
	if(x1==t)
	{
		printf("1\n");
		continue;
	}
	if(a==0)
	{
		if(b==t)printf("2\n");
		else printf("-1\n");
		continue;
	}
		if(a==1)
	{
		if(b>0){
		exgcd(b,P);
			
		printf("%lld\n",(x+P)%P*(t-x1+P)%P+1);	
		}
		else printf("-1\n");
		continue;
	}
	xishu=(x1*(a-1)%P+b)%P;
	m=sqrt(P)+1;
	t=(t*(a-1)%P+b)%P;
	for(i=m;i>=1;i--)
	{
		ma[xishu*ksm(a,i-1)%P]=i;
	}
	for(i=0;i<=m;i++)
	{
		ll mi=ksm(a,m*i);
		exgcd(mi,P);
		 mi=ma[(x*t%P+P)%P];	
		if(mi>0)
		{
			printf("%lld\n",i*m+mi);
			jieshu=1;		
			break;
		}
	}
	if(jieshu==0)
	{
		printf("-1\n");
	}
		
ma.clear();
	
    }
}