bzoj3122: [Sdoi2013]随机数生成器
3122: [Sdoi2013]随机数生成器
Description
Input
输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数。
接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据。保证X1和t都是合法的页码。
注意:P一定为质数
Output
共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。
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;
}