bzoj3122: [Sdoi2013]随机数生成器(BSGS)

http://www.lydsy.com/JudgeOnline/problem.php?id=3122

 

等比数列求和公式+BSGS

 

#include<map>
#include<cmath>
#include<cstdio>
#include<iostream>

using namespace std;

int p,a,b,x1,t;

map<int,int>mp;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

int Pow(int x,int y)
{
    int r=1;
    for(;y;x=1LL*x*x%p,y>>=1)
        if(y&1) r=1LL*r*x%p;
    return r;
}

    void force()
    {
        int ans=-1;
        int last=x1,now;
        for(int i=2;i<=p;++i)
        {
            now=(1LL*a*last+b)%p;
            if(now==t)
            {
                ans=i;
                break;
            }
            last=now;
        }
        printf("%d\n",ans);
    }    

    void A1()
    {
        if(!b) printf("-1\n");
        else printf("%d\n",int((1LL*(t-x1+p)%p*Pow(b,p-2)%p+1)%p));
    }

    void BSGS()
    {
        if(!a)
        {
            if(t==x1) printf("1\n");
            else if(t==b) printf("2\n");
            else printf("-1\n");
            return;
        }
        int ans=-1;
        mp.clear();
        int B=1LL*t*Pow(x1,p-2)%p;
        int m=ceil(1.0*sqrt(1.0*p));
        int mul=B;
        mp[B]=0;
        for(int i=1;i<m;++i)
        {
            mul=1LL*mul*a%p;
            mp[mul]=i;
        }
        mul=1;
        int am=Pow(a,m);
        for(int i=1;i<=m;++i)
        {
            mul=1LL*mul*am%p;
            if(mp.find(mul)!=mp.end())
            {
                ans=i*m-mp[mul];
                break;
            }
        }
        if(ans!=-1) ans++;
        printf("%d\n",ans);
    }
    
void bsgs()
{
        if(!a)
        {
            if(t==x1) printf("1\n");
            else if(t==b) printf("2\n");
            else printf("-1\n");
            return;
        }
        int ans=-1;
        mp.clear();
        int tmp=1LL*b*Pow(a-1,p-2)%p;
        int B=1LL*(t+tmp)*Pow(x1+tmp,p-2)%p;
        int m=ceil(1.0*sqrt(1.0*p));
        int mul=B;
        mp[B]=0;
        for(int i=1;i<m;++i)
        {
            mul=1LL*mul*a%p;
            mp[mul]=i;
        }
        mul=1;
        int am=Pow(a,m);
        for(int i=1;i<=m;++i)
        {
            mul=1LL*mul*am%p;
            if(mp.find(mul)!=mp.end())
            {
                ans=i*m-mp[mul];
                break;
            }
        }
        if(ans!=-1) ans++;
        printf("%d\n",ans);
}

int main()
{
    //freopen("random.in","r",stdin);
    //freopen("random.out","w",stdout);
    int T;
    read(T);
    while(T--)
    {
        read(p); read(a); read(b); read(x1); read(t);
        if(x1==t) 
        {
            printf("1\n");
            continue;
        }
        if(p<=100) force();
        else if(a==1) A1();
        else if(!b) BSGS();
        else bsgs();
    }
}

 

posted @ 2018-03-06 16:03  TRTTG  阅读(311)  评论(0编辑  收藏  举报