BZOJ 3122 随机数生成器

http://www.lydsy.com/JudgeOnline/problem.php?id=3122

题意:给出p,a,b,x1,t 

已知xn=a*xn-1+b%p,求最小的n令xn=t

首先,若x1=t,则返回1

         若a=0,则若b=t 返回2,否则无解

         若a=1,则T=t-x1+p%p,可以列出方程

         b*x+p*y==T % p

         若a>=2,则根据等比数列和可得

         xn=t=x1*a^(n-1)+b*(a^(n-1)-1)/(a-1) %p

         由于p为质数,所以令c=inv[a-1]=(a-1)^(p-2)

         x1*a^(n-1)+b*c*(a^(n-1))==b*c+t %p

         (x1+b*c)*(a^(n-1))==b*c+t % p

         令A=x1+b*c,B=p,C=b*c+t

         则就是解A*X+B*Y==C %p

         解出来X=a^(n-1),然后这个用BSGS求就可以了

  1 #include<algorithm>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<map>
  7 #define ll long long
  8 ll p;
  9 ll read(){
 10     char ch=getchar();ll t=0,f=1;
 11     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 12     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
 13     return t*f;
 14 }
 15 ll Pow(ll x,ll y){
 16     ll res=1;
 17     if (x<0) x=(x+p)%p;
 18     while (y){
 19         if (y%2) res=(res*x)%p;
 20         x=(x*x)%p;
 21         y/=2;
 22     }
 23     return res;
 24 }
 25 ll gcd(ll a,ll b){
 26     if (b==0) return a;
 27     else return gcd(b,a%b);
 28 }
 29 void exgcd(ll a,ll b,ll &x,ll &y){
 30     if (b==0){
 31         x=1;
 32         y=0;
 33         return;
 34     }
 35     exgcd(b,a%b,x,y);
 36     ll T=x;
 37     x=y;
 38     y=T-(a/b)*y;
 39 }
 40 ll reverse(ll X){
 41     ll A=X,B=p;
 42     ll x,y;
 43     exgcd(A,B,x,y);
 44     return (x%p+p)%p;
 45 }
 46 ll work(ll a,ll b){
 47     a%=p;
 48     if (a==0){
 49         if (b==0) return 1;
 50         else return -1;
 51     }
 52     std::map<ll,int> mp;
 53     ll m=sqrt(p)+1,I=1,Im=Pow(a,p-1-m),t=1;
 54     mp.clear();mp[1]=m+1;
 55     for (int i=1;i<m;i++){
 56         t=t*a%p;
 57         if (!mp[t]) mp[t]=i;    
 58     }
 59     for (int k=0;k<m;k++){
 60         int i=mp[I*b%p];
 61         if (i){
 62             if (i==m+1) i=0;
 63             return i+k*m;
 64         }
 65         I=I*Im%p;
 66     }
 67     return -1;
 68 }
 69 ll solve(ll a,ll b,ll x1,ll t){
 70     if (t==x1) {
 71             return 1;
 72     }
 73     if (a==0){
 74             if (b==t){
 75                 return 2;
 76             }
 77             return -1;
 78     }
 79     if (a==1){
 80             ll A=b,B=p,T=(t-x1+p)%p;
 81             ll D=gcd(A,B);
 82             if (T%D) {
 83                 return -1;
 84             }
 85             T/=D;
 86             ll x,y;
 87             exgcd(A,B,x,y);
 88             x=(x*T)%p;
 89             while (x<0) x+=p;
 90             return x+1;
 91     }
 92     ll c=Pow(a-1,p-2);
 93     ll A=(b*c+x1)%p,B=p,T=(b*c+t)%p;
 94     if (A<0) A=(A+p)%p;
 95     if (B<0) B=(B+p)%p;
 96     ll D=gcd(A,B);
 97     if (T%D){
 98         return -1;
 99     }
100     T/=D;
101     ll x,y;
102     exgcd(A,B,x,y);
103     while (x<0) x=(x+p)%p;
104     x=(x*T)%p;
105     ll ans=work(a,x);
106     if (ans!=-1) return ans+1;
107     else return ans;
108 }
109 int main(){
110     int Tcase;
111     scanf("%d",&Tcase);
112     while (Tcase--){
113         ll a,b,x1,t;
114         p=read();a=read();b=read();x1=read();t=read();
115         printf("%lld\n",solve(a,b,x1,t));
116     }
117 }

 

posted @ 2016-06-13 20:23  GFY  阅读(487)  评论(0编辑  收藏  举报