2017.9.25 随机数生成器 失败总结

、这个题要用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();
	
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值