• BZOJ 1420: Discrete Root (原根+BSGS)


    题意

    已知kk, aa, pp. 求 xka (mod p)x^kequiv a (mod p) 的所有根. 根的范围[0,p1][0,p-1]. pp为质数

    分析

    因为pp是质数,那么一定有原根.设为gg.
    原根的性质如下:

    • 对于[1,p1][1,p-1]的所有ii,一定存在x[1,p1]xin[1,p-1]使得gxi (mod p)g^xequiv i (mod p). 此时设xxI(i)I(i).

    1.1.那么当aa等于00

    • 只有一个根就是00

    2.2.a[1,p1]ain[1,p-1]

    • 画画柿子xka (mod p)(gI(x))ka (mod p)(gk)I(x)a (mod p)egin{aligned}x^k&equiv a (mod p)\(g^{I(x)})^k&equiv a (mod p)\(g^{k})^{I(x)}&equiv a (mod p)end{aligned}
      我们知道gkg^k,知道aa,知道pp.直接BSGSBSGS就行了.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int g, prime[100], cnt;
    inline int qpow(int a, int b, int c) {
        int re = 1;
        while(b) {
            if(b&1) re = 1ll * re * a % c;
            a = 1ll * a * a % c; b >>= 1;
        }
        return re;
    }
    inline void Factor(int N) {
        int tmp = N;
        for(int i = 2; i*i <= N; ++i)
            if(tmp % i == 0) {
                prime[++cnt] = i;
                while(tmp % i == 0) tmp /= i;
            }
        if(tmp > 1) prime[++cnt] = tmp;
    }
    inline int Get_g(int p) { //找原根
        Factor(p-1);
        for(int g = 2; ; ++g) {
            bool flg = true;
            for(int i = 1; i <= cnt; ++i)
                if(qpow(g, (p-1)/prime[i], p) == 1)
                    { flg = 0; break; }
            if(flg) return g;
        }
    }
    map<int, int>myhash;
    vector<int>ans;
    inline void Baby_Step_Giant_Step(int a, int b, int p) {
        if(b == 1) ans.push_back(0);
        myhash.clear();
        int m = int(sqrt(p) + 1);
        LL base = b;
        for(int i = 0; i < m; ++i) {
            myhash[base] = i;
            base = 1ll * base * a % p;
        }
        base = qpow(a, m, p);
        LL tmp = 1;
        for(int i = 1; i <= m+1; ++i) {
            tmp = 1ll * tmp * base % p;
            if(myhash.count(tmp))
                ans.push_back(i*m - myhash[tmp]);
        }
    }
    int main() {
        int p, k, a, g;
        scanf("%d%d%d", &p, &k, &a);
        if(!a) return puts("1"), puts("0"), 0;
        //(g^I(x))^k = a (mod p)
        //(g^k)^I(x) = a
        Baby_Step_Giant_Step(qpow(g = Get_g(p), k, p), a, p);
        for(int i = 0, siz = ans.size(); i < siz; ++i)
            ans[i] = qpow(g, ans[i], p);
        sort(ans.begin(), ans.end());
        int siz = ans.size();
        siz = unique(ans.begin(), ans.end()) - ans.begin();
        printf("%d
    ", siz);
        for(int i = 0; i < siz; ++i)
            printf("%d
    ", ans[i]);
    
    }
    
    
  • 相关阅读:
    gitlab 安装升级
    fping 命令
    sed 命令
    rm 命令
    sort 命令
    第十六单元
    第十五单元
    第十三单元
    第十二单元
    第十一单元
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039307.html
Copyright © 2020-2023  润新知