[日常摸鱼]bzoj3122 [Sdoi]2013 随机数生成器

又是写了一晚上才过的题…

题意:有一个数列$x_n=(ax_{n-1}+b) mod p$,给你$x_1,a,b,p,t$,求最小的$x_i=t$的$i$,可能不存在

 


 

 

一开始很自然的推出了式子$x_n \equiv a^{n-1}x_1+b*\frac{a^{n-1}-1}{a-1} \pmod p$

这时候如果$a=1$的话就特判一下然后用exgcd做

否则让$x_n=T$得到$a^{n-1}*(ax_1-x_1+b) \equiv (a-1)T+b \pmod p$

如果$ax_1-x_1+b$存在逆元的话就两边乘上逆元然后BSGS做,不存在逆元就无解啦

 

然后我判a=0的时候当t=b的时候返回了1…然后交上去一直wa还拍不出来

 

#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lint;

inline lint read()
{
    lint s=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
    return s*f; 
}

map<lint,lint>x;

inline lint gcd(lint a,lint b)
{
    return !b?a:gcd(b,a%b);
}

inline lint exgcd(lint a,lint b,lint &x,lint &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }lint d=exgcd(b,a%b,x,y);
    lint tx,ty;tx=y;ty=x-a/b*y;
    x=tx;y=ty;
    return d;
}

inline lint mul_mod(lint a,lint b,lint p)
{
    lint res=a%p*b%p;res=(res%p+p)%p;return res;
}

inline lint pow_mod(lint a,lint b,lint p)
{
    lint res=1;
    for(;b;b>>=1,a=(a*a)%p)if(b&1)res=(res*a)%p;
    return res;
}

inline lint inv(lint a,lint p)
{
    return mul_mod(pow_mod(a,p-2,p),1,p);
}

inline lint BSGS(lint a,lint b,lint p)
{
    a%=p;x.clear();
    if(a==0&&b==0)return 1;
    if(a==0)return -1;
    lint m=ceil(sqrt(p)),t=1;
    x[1]=m+1;
    for(register lint i=1;i<m;i++)
    {
        t=mul_mod(t,a,p);
        if(!x[t])x[t]=i;
    }
    lint tmp=pow_mod(a,p-1-m,p),inv=1;
    for(register lint k=0;k<m;k++)
    {
        lint i=x[b*inv%p];
        if(i)
        {
            if(i==m+1)i=0;
            return k*m+i;
        }
        inv=mul_mod(inv,tmp,p);
    }
    return -1;
}

inline lint solve(lint p,lint a,lint b,lint x,lint t)
{
    if(x%p==t%p)return 1;
    if(a==0)
    {
        if(b%p==t%p)return 2;//before this is return 1; T_T
        return -1;
    }
    if(a==1)
    {
        lint k,l,c,tmp;c=((t-x)%p+p)%p;
        tmp=gcd(b,p);
        if(c%tmp)return -1;
        c/=tmp;
        exgcd(b,p,k,l);
        k=k*c%p;
        k=(k%p+p)%p;
        return k+1;
    }
    lint q=(x*a%p-x+b)%p;q=(q+p)%p;
    if(gcd(q,p)!=1)return -1;
    lint tmp=((a-1)*t+b)%p*inv(q,p);tmp=mul_mod(tmp,1,p);
    lint res=BSGS(a,tmp,p);
    if(res==-1)return -1;
    return ((res%p)+p)%p+1;
}

int main()
{
    lint t=read();
    while(t--)
    {
        lint p,a,b,x,T;
        p=read();a=read();b=read();x=read();T=read();
        printf("%lld\n",solve(p,a,b,x,T));
    }
    return 0;
}
View Code

 

posted @ 2017-12-06 19:05  yoshinow2001  阅读(161)  评论(0编辑  收藏  举报