zoukankan      html  css  js  c++  java
  • 2019牛客多校第五场C generator 2(BSGS)题解

    题意:

    传送门
    已知递推公式(x_i = a*x_{i - 1} + bmod p)(p)是素数,已知(x_0,a,b,p),给出一个(n)(v),问你满足(x_i = v)(i < n)的最小的(i)是多少。

    思路:

    经过一些举例我们可以发现(x_i = a^ix_0 + bfrac{a^i-1}{a-1}mod p),当(a eq 1)可得(a^i = frac{(a-1)v+b}{(a-1)x_0+b}mod p)。再当(a geq 1)时可用(BSGS)求解,其他直接特判。
    但是因为(q)的存在,如果直接套模板复杂度(O(sqrt p + qsqrt p))(3e7*T)(TLE)。因为每组询问的预处理都相同,那么我们不妨把预处理扩大,这样每次查询所要暴力的次数就变小了。预处理大小设为(1e6),手写(Hash)更快。

    代码:

    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 300 + 5;
    const int INF = 0x3f3f3f3f;
    const ull seed = 131;
    const ll MOD = 1e9;
    using namespace std;
    
    //BSGS
    const int M = 5e6;
    int hs[M], head[M], nex[M], id[M], top;
    void _insert(ll x, int y){
        int k = x % M;
        hs[top] = x, id[top] = y, nex[top] = head[k], head[k] = top++;
    }
    int _find(ll x){
        int k = x % M;
        for(int i = head[k]; i != -1; i = nex[i]){
            if(hs[i] == x) return id[i];
        }
        return -1;
    }
    ll ppow(ll a, ll b, ll mod){
        ll ret = 1;
        while(b){
            if(b & 1) ret = ret * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return ret;
    }
    ll loop, up;
    void preBSGS(ll p, ll a){   // a^x = b mod p
        memset(head, -1, sizeof(head));
        top = 1;
        up = ceil(1e6);
        ll t = 1;
        for(int i = 0; i <= up; i++){
            if(i == up) loop = t;
            _insert(t, i);
            t = 1LL * t * a % p;
        }
    }
    ll BSGS(ll A, ll B, ll P){  // a^x = b mod p
        ll m = ceil(P * 1.0 / 1e6);
        ll obj = ppow(B, P - 2, P), x;
        for(int i = 1; i <= m; i++){
            obj = 1LL * obj * loop % P;
            if((x = _find(obj)) != -1){
                return 1LL * i * up - x;
            }
        }
        return -1;
    }
    ll n, x0, a, b, p, Q;
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%lld%lld%lld%lld%lld", &n, &x0, &a, &b, &p);
            scanf("%lld", &Q);
            preBSGS(p, a);
            while(Q--){
                ll v;
                scanf("%lld", &v);
                if(a == 0){
                    if(v == x0) printf("0
    ");
                    else if(v == b && n - 1 >= 1) printf("1
    ");
                    else printf("-1
    ");
                }
                else if(a == 1){
                    v = ((v - x0) % p + p) % p;
                    if(b == 0){
                        printf("%d
    ", v == 0? 0 : -1);
                        continue;
                    }
                    ll ans = 1LL * v * ppow(b, p - 2, p) % p;
                    printf("%lld
    ", ans >= n? -1 : ans);
    
                }
                else{
                    ll ret = (a * v % p - v + b) % p;
                    ret = ret * ppow((a * x0 - x0 + b) % p, p - 2, p) % p;
                    ret = (ret + p) % p;
                    ll ans = BSGS(a, ret, p);
                    printf("%lld
    ", ans >= n? -1 : ans);
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    apache http 403 Forbidden error
    Python dictionary
    Python The standard programe tructure
    SVN server setup 2
    SVN Server setup 3
    Cent OS下中文乱码的解决方法
    Start to enjoin python
    Linux Client RapidSVN
    使用 F12 开发人员工具调试 HTML 和 CSS(IE浏览器)
    十条不错的编程观点
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11403974.html
Copyright © 2011-2022 走看看