题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3122
题目大意:Xn+1=(aXn+b)%P 0<=a,b<=P-1<=1e9+1 求最小的n满足Xn=t。0<=t<=P-1,且P为质数。
题目分析:我们将递推式展开得到:Xn+1=a^n*x1+b+a^2*b+···+a^(n-1)*b。后半部分我们用等比数列进行化简。我们设d=(b/(a-1))%P。那么Xn+1=a^n*x1+d*a^n-db。令(x1+d)为p,x1+bd为q。那么q=p*a^n。令x=q/p。则a^n=x(mod P) 到这里后我们利用BSGS进行计算即可。注意本题的细节部分:x1==t,a==0,a==1
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<map> using namespace std; typedef long long LL; LL pow_mod(LL a,LL i,LL n) { if (i==0) return 1%n; LL temp=pow_mod(a,i>>1,n); temp=temp*temp%n; if (i&1) temp=(LL) temp*a%n; return temp; } void extendgcd(LL a,LL b,LL &d,LL &x,LL &y) { if(b==0){d=a;x=1;y=0;return;} extendgcd(b,a%b,d,y,x); y-=x*(a/b); } LL GetNi(LL A,LL M) { LL rex=0,rey=0; LL td=0; extendgcd(A,M,td,rex,rey); return (rex%M+M)%M; } LL bsgs(int x,int n,int m) { map<LL,int> rec; int s=(int)(sqrt((double)m)); for(;(LL)s*s <= m;) s++; LL cur=x%m; rec[1]=0; for (int i=1;i<s;i++) { if (rec[cur]==0&&cur!=1) rec[cur]=i; cur=(cur*x)%m; } LL mul=cur; cur=1; for (int i=0;i<s;i++) { LL more=(LL)n*pow_mod(cur,m-2,m)%m; if (rec.count(more)) return i*s+rec[more]+1; cur=(cur*mul)%m; } return -1; } LL p,a,b,x1,t; int main() { int T; cin>>T; while (T--) { cin>>p>>a>>b>>x1>>t; if (t==x1) { printf("1\n"); continue; } if (a==0) { if (b==t) cout<<2<<endl; else cout<<-1<<endl; continue; } if (a==1) { t=(t+p-x1+b)%p; t=(t*GetNi(b,p))%p; if (t>0) printf("%d\n",t); else if(b==0) printf("-1\n"); else printf("%d\n",p); continue; } LL d=(b*GetNi(a-1,p))%p; t=(t+d)%p; x1=(x1+d)%p; t=(t*GetNi(x1,p))%p; cout<<bsgs(a,t,p)<<endl; } return 0; }