bzoj3122: [Sdoi2013]随机数生成器
难得一个完全自己推出来的数论题,结果还因为特判挂了好几个星期,今天才把特判打出来A掉。
开始以为要求ax+bx≡c(mod p)这种形式的方程,然而并不会解,nc哥告诉我不是,我才想起来求通项公式(推了一节数学课推出来了)(mikufun推了一节物理课),
$X_{i+1}=aX_i+b=a^2X_{i-1}+ab+b=a^3X_{i-2}+a^2b+ab+b$
由此可得:
$X_n=X_1*a^{n-1}+b+ab+...+a^{n-2}b$
$ =X_1*a^{n-1}+b(a^0+a^1+...+a^{n-2})$
$ =X_1*a^{n-1}+b\frac{a^{n-1}-1}{a-1}$
$ =\frac{(a-1)X_1a^{n-1}}{a-1}+\frac{ba^{n-1}}{a-1}-\frac{b}{a-1}$
$ =\frac{[(a-1)X_1+b]a^{n-1}}{a-1}-\frac{b}{a-1}$
$\frac{[(a-1)X_1+b]a^{n-1}}{a-1}-\frac{b}{a-1}\equiv t(mod p)$
$[(a-1)X_1+b]a^{n-1}\equiv (a-1)t+b (mod p)$
bsgs解即可。
然而这题不加特判会爆0……
1 if(x1==t){cout<<1<<endl;continue;} 2 if(a==1) 3 { 4 if(!b){cout<<-1<<endl;continue;} 5 else {cout<<(t-x1+p)*poww(b,p-2,p)%p+1<<endl;continue;} 6 } 7 if(a==0) 8 { 9 cout<<(b==t?2:-1)<<endl; 10 continue; 11 }
#include<iostream> #include<cstdio> #include<cmath> #include<map> #define LL long long #define int LL using namespace std; int T; LL p,a,b,x1,t; LL poww(LL a,LL b,LL p) { LL ans=1; while(b) { if(b&1)ans=ans*a%p; a=a*a%p; b=b>>1; } return ans%p; } LL bsgs(LL a,LL b,LL p) { map<LL,LL>mp;mp.clear(); LL m=ceil(sqrt(p*1.0)); for(int j=0;j<=m;j++) { LL val=b*poww(a,j,p)%p; mp[val]=j; } a=poww(a,m,p); if(!a)return !b?0:-1; for(int i=0;i<=m;i++) { LL val=poww(a,i,p); LL j=mp.find(val)==mp.end()?-1:mp[val]; if(j>=0 && i*m-j>=0)return i*m-j; } return -1; } signed main() { cin>>T; while(T--) { scanf("%lld%lld%lld%lld%lld",&p,&a,&b,&x1,&t); if(x1==t){cout<<1<<endl;continue;} if(a==1) { if(!b){cout<<-1<<endl;continue;} else {cout<<(t-x1+p)*poww(b,p-2,p)%p+1<<endl;continue;} } if(a==0) { cout<<(b==t?2:-1)<<endl; continue; } LL tb,inv; inv=poww((a-1)*x1%p+b,p-2,p); inv=(inv%p+p)%p; tb=((a-1)*t%p+b)%p*inv%p; LL ans=bsgs(a,tb,p); cout<<(ans==-1?-1:ans+1)%p<<endl; } }
波澜前,面不惊。