码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3122: [Sdoi2013]随机数生成器

时间:2018-02-28 01:18:09      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:for   print   text   tchar   class   sdoi2013   efi   bzoj3122   hint   

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]随机数生成器

标签:for   print   text   tchar   class   sdoi2013   efi   bzoj3122   hint   

原文地址:https://www.cnblogs.com/zhou888/p/8481580.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!