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 }