天天看點

2019牛客暑期多校訓練(第五場)C-generator 2

2019牛客暑期多校訓練(第五場)C-generator 2

題目描述

There is a sequence of length n:x0,x1,x2,…,xn−1. Please answer Q queries. Each query consists of one integer v, asking the minimum index i such that xi=v. If the sequence doesn’t have any number with value v, you only need to output -1.

Does the problem look simple? Surprise! The value of n may be as large as 1018!

Because n is so large. We will only give you four integers x0,a,b,p to generate the sequence. For all i>0, the sequence is generated as xi=(a⋅xi−1+b)mod p.

輸入描述:

The first line of input contains an integer T (T≤4) denoting there are T tests in the input.

Each test contains Q+2 lines.

The first line of each test contains five integers n,x 0,a,b,p (1≤n≤1018,0≤xp,a,b<p≤109+9, p is a prime number).

The second line contains one integer Q (Q≤1000).

Each of the following Q lines contains one integer v (0≤v<p).

輸出描述:

For each query, print one integer as the answer in one line.

示例1

輸入

3

1000000009 1 1 1 1000000009

5

1

10

1000000008

1000000007

100000009 1 1 1 1000000009

3

10

1000000008

1000000000000000000 1 5 0 1000000007

6

1

10

1000000006

12345678

1234567

輸出

1000000008

9

1000000007

1000000006

-1

9

-1

-1

381838283

500000003

652614354

581802189

說明

For the first test, the sequence looks like 1, 2, 3, …, 1000000008, 0. So the position of the first occurrence of value v is v - 1 except for value 0 which occurs at 1000000008.

示例2

輸入

2

1000000000000000000 5 2 2 1000000007

4

1

2

3

5 1 0 3 950000017

4

1

2

3

輸出

115068150

342074

115068151

-1

-1

-1

1

題意

已知x[i]=(a*x[i-1]+b)%p,求滿足等式的x數組的下标,且該下标小于n。若不存在則輸出-1。

思路

BSGS算法(北上廣深算法,拔山蓋世算法 )。

首先,我們可以根據遞推式求出x[n]關于x[0]的表達式。

然後。。。然後。。。然後。。。

就沒有然後了。

發現是一個BSGS的式子。

求就完了。

坑點

真特麼多。

首先,這題時間卡的很緊,如果用map哈希的話很容易逾時,是以我後來用了unordered_map。

然後,我隊友用鍊式前向星手寫哈希跑了627ms,tql。

大佬的CSDN個人首頁

之後還加了很多小優化,具體的就看BSGS和initBSGS函數部分的代碼吧。

代碼

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=1e5+5;

ll quickpow(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

unordered_map<int,int> M;
ll up,down,mul;

void initBSGS(ll y,ll p)
{
    M.clear();
    up=ceil(pow(p,2.0/3));
    down=ceil(pow(p,1.0/3));
    ll num=1;
    for(int i=0; i<=up; i++)
    {
        if(i==up)
            mul=num;
        M[num]=i;
        num=num*y%p;
    }
}

ll BSGS(ll y,ll z,ll p)
{
    ll num=quickpow(z,p-2,p);
    for(int i=1; i<=down+1; i++)
    {
        num=num*mul%p;
        if(M.count(num))
            return i*up-M[num];
    }
    return -1;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n,x0,a,b,q,v,mod;
        scanf("%lld%lld%lld%lld%lld",&n,&x0,&a,&b,&mod);
        initBSGS(a,mod);
        scanf("%lld",&q);
        while(q--)
        {
            scanf("%lld",&v);
            if(a==0)
            {
                if(v==x0)
                    printf("0\n");
                else if(v==b&&n>=1)
                    printf("1\n");
                else
                    printf("-1\n");
            }
            else if(a==1)
            {
                if(b==0)
                    printf("%d\n",v==x0?0:-1);
                else
                {
                    int invb=quickpow(b,mod-2,mod);
                    v=((v-x0+mod)%mod)*invb%mod;
                    printf("%d\n",v<n?v:-1);
                }
            }
            else
            {
                if(x0==0&&b==0)
                    printf("%d\n",v==0?0:-1);
                else
                {
                    ll num=quickpow((((1-a+mod)%mod)*x0%mod-b+mod)%mod,mod-2,mod)*((((1-a+mod)%mod)*v%mod-b+mod)%mod)%mod;
                    ll ans=BSGS(a,num,mod);
                    if(ans<n)
                        printf("%lld\n",ans);
                    else
                        printf("-1\n");
                }
            }
        }
    }
    return 0;
}