1. 程式人生 > 實用技巧 >[SDOI2013] 隨機數生成器

[SDOI2013] 隨機數生成器

題意:

給定$a,b,p,x_1$,$\forall i>1,x_i = ax_{i-1} +b$。

求最小的$i$滿足$x_i = t$,若無解則輸出-1。

$0\leq a,b,x_1 , t<p\leq 10^{9},p是質數$。

題解:

挺水的一道題,展開之後BSGS即可。

但$a\leq 1$的地方需要特判,還巨複雜,有高中數學題內味了。

複雜度$O(\sqrt{p})$。

套路:

  • 推式子時:注意特判整體乘除0的情況。

程式碼:

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define
inf 0x7fffffff #define ll long long #define rint register int #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; ll p; unordered_map<ll,ll> M; inline ll read(){ ll x
=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline ll pw(ll a,ll b){ll r=1;while(b)r=(b&1)?r*a%p:r,a=a*a%p,b>>=1;return r;} inline ll inv(ll x){return pw(x,p-2);} inline ll BSGS(ll a,ll b){ M.clear(); ll n
=ceil(sqrt(p)),ans=1ll<<62; for(ll i=0,t=1;i<=n;i++,t=t*a%p) M[b*t%p]=i; for(ll i=0,t=1,w=pw(a,n);i<=n;i++,t=t*w%p) if(M[t] && i*n-M[t]>=0) ans=min(ans,i*n-M[t]); if(ans==(1ll<<62)) return -1; else return ans; } int main(){ //freopen("P3306_2.in","r",stdin); //freopen("1.out","w",stdout); ll T=read(); while(T--){ p=read(); ll a=read(),b=read(),x1=read(),t=read(); if(a==0){ if(x1==t) printf("1\n"); else if(b==t) printf("2\n"); else printf("-1\n"); } else if(a==1){ if(b==0){ if(x1==t) printf("1\n"); else printf("-1\n"); } else printf("%lld\n",(t-x1+p)*inv(b)%p+1); } else{ if((x1+(b*inv(a-1)))%p==0){ if((t+(b*inv(a-1)))%p==0) printf("1\n"); else printf("-1\n"); } else{ ll y=(t+(b*inv(a-1)))%p*inv((x1+(b*inv(a-1)))%p)%p; ll ans=BSGS(a,y)+1; if(ans==0) printf("-1\n"); else printf("%lld\n",ans); } } } return 0; } //59 38 24 25 5
隨機數生成器