1. 程式人生 > >bzoj3122: [Sdoi2013]隨機數生成器

bzoj3122: [Sdoi2013]隨機數生成器

typedef its names 隨機 pre efi IT 由於 %d

3122: [Sdoi2013]隨機數生成器

Description

技術分享圖片

Input

技術分享圖片

Output

技術分享圖片

HINT

$ 0 \leqslant a \leqslant P-1,0 \leqslant b \leqslant P-1,2 \leqslant P \leqslant 10^9 $

BSGS裸題

把線性遞推式轉化為通項公式為

$
x[n] = x1 * A^{n-1} + \frac {B*A^{n-1}} {A-1} = t
$

移項,得:

$
(x1 + \frac {B} {A-1}) * A^{n-1} = t - \frac {B} {A-1}
$

但是有幾種情況要特判

\(t = x1\)

時,輸出1

當$a = 0 $時,看t與b是否相等

當$a = 1 $時,由於等比數列公比不確定也要特判,判一下exgcd就行了

剩下的BSGS就可以了

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef long long ll;
inline int
read(){ int x; char c; int f=1; while((c=getchar())!=‘-‘ && (c>‘9‘ || c<‘0‘)); if(c==‘-‘) c=getchar(),f=-1; x=c^‘0‘; while((c=getchar())>=‘0‘ && c<=‘9‘) x=(x<<1)+(x<<3)+(c^‘0‘); return x*f; } inline ll readll(){ ll x; char c; int
f=1; while((c=getchar())!=‘-‘ && (c>‘9‘ || c<‘0‘)); if(c==‘-‘) c=getchar(),f=-1; x=c^‘0‘; while((c=getchar())>=‘0‘ && c<=‘9‘) x=(x<<1ll)+(x<<3ll)+(c^‘0‘); return x*f; } map<int,int> mp; int ksm(int x,int y,int mod){ int res=1; while(y){ if(y&1) res=1ll*res*x%mod; x=1ll*x*x%mod; y>>=1; } return res; } int exgcd(int &x,int &y,int a,int b){ if(!b){ x=1,y=0; return a; } int res=exgcd(y,x,b,a%b); y-=a/b*x; return res; } int solve(int a,int b,int c,int mod){ int x,y; int res=exgcd(x,y,a,b); if(c%res) return -1;c/=res; x=(x%mod+mod)%mod; return 1ll*x*c%mod; } int bsgs(int A,int B,int mod){ mp.clear(); int m=(int)sqrt(mod)+1,inv=ksm(A,m,mod); inv=ksm(inv,mod-2,mod); mp[1]=m+1; for(int i=1,x=A;i<m;++i,x=1ll*x*A%mod) if(!mp[x]) mp[x]=i; for(int i=0;i*m<mod;++i){ int x=mp[B]; if(x) return i*m+x%(m+1); B=1ll*B*inv%mod; } return -1; } int main(){ int T=read(); while(T--){ int p=read(),A=read(),B=read(),x1=read(),t=read(); if(x1==t){ printf("1\n"); continue; } x1%=p; if(A==0){ if(B==t) printf("2\n"); else printf("-1\n"); continue; } if(A==1){ int x=solve(B,p,(t-x1+p)%p,p); if(x==-1) printf("-1\n"); else printf("%d\n",x+1); continue; } int u=1ll*B*ksm(A-1,p-2,p)%p; int x=solve((u+x1)%p,p,(t+u)%p,p); if(x==-1) printf("-1\n"); else{ x=bsgs(A,x,p); if(x==-1) printf("-1\n"); else printf("%d\n",x+1); } } return 0; }

bzoj3122: [Sdoi2013]隨機數生成器