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;
}
posted @ 2018-02-27 23:41  zhou888  阅读(181)  评论(1编辑  收藏  举报