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
0
1
10
1000000008
1000000007
100000009 1 1 1 1000000009
3
0
10
1000000008
1000000000000000000 1 5 0 1000000007
6
0
1
10
1000000006
12345678
1234567
输出
1000000008
0
9
1000000007
1000000006
-1
9
-1
-1
0
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
0
1
2
3
5 1 0 3 950000017
4
0
1
2
3
输出
115068150
342074
115068151
-1
-1
0
-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;
}

发布了42 篇原创文章 · 获赞 6 · 访问量 4036

猜你喜欢

转载自blog.csdn.net/qq_43383246/article/details/98994599