BZOJ 3122 随机数生成器

Posted on 2016-10-14 13:44  ziliuziliu  阅读(119)  评论(0编辑  收藏  举报

其实我觉得直接矩阵BSGS也可以做?

推下式子。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
long long T,mod,a,b,x1,t,p,q,r,x,y;
map <long long,long long> mp;
long long f_pow(long long a,long long b)
{
    long long ans=1,base=a;
    while (b)
    {
        if (b&1) ans=(ans*base)%mod;
        base=(base*base)%mod;
        b>>=1;
    }
    return ans;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if (b==0)
    {
        x=1;y=0;
        return a;
    }
    long long d=exgcd(b,a%b,x,y);
    long long t=x;
    x=y;y=t-(a/b)*y;
    return d;
}
long long BSGS()
{
    mp.clear();
    if (p==r) return 0;
    long long m=(long long)(sqrt(1.0*mod)+1),base=r;
    for (long long i=0;i<m;i++)
    {
        mp[base]=i;
        base=(base*q)%mod;
    }
    long long tmp=f_pow(q,m);base=(tmp*p)%mod;
    for (long long i=1;i<=m+1;i++)
    {
        if (mp.count(base)) return i*m-mp[base];
        base=(base*tmp)%mod;
    }
    return -2;
}
int main()
{
    scanf("%lld",&T);
    for (long long i=1;i<=T;i++)
    {
        scanf("%lld%lld%lld%lld%lld",&mod,&a,&b,&x1,&t);
        if (x1==t) printf("1\n");
        else if (!a)
        {
            if (b==t) printf("2\n");
            else printf("-1\n");
        }
        else if (a==1)
        {
            long long d=exgcd(b,mod,x,y);
            p=(t-x1+b+mod)%mod;
            if (p%d) printf("-1\n");
            else
            {
                if (x<0) x+=mod;
                x=(x*(p/d))%mod;if (!x) x=mod;
                printf("%d\n",x);
            }
        }
        else
        {
            p=x1*(a-1)+b;p%=mod;
            q=a;q%=mod;
            r=(t*(a-1)+b)%mod;
            printf("%lld\n",BSGS()+1);
        }
    }
    return 0;
}