2017.9.25 随机数生成器 失败总结

来源:互联网 发布:linux 查看服务器状态 编辑:程序博客网 时间:2024/06/06 01:30

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