• 【数学】BSGS算法


    BSGS算法

    求解 (a^xequiv b (mod m)) 其中 (gcd(a,m)=1)

    随便取一个 (x_1) ,则可以把 (x) 通过 (x=kx_1-x_2) 替换,其中 (x_2<x_1) 。则 (a^{kx_1-x_2}equiv b (mod m))

    (a^{kx_1}equiv bcdot a^{x_2} (mod m))

    枚举 (x_2) 的值,算出所有的右边的情况,存到一个Hash表里面,使得可以通过 (bcdot a^{x_2}) 查到 (x_2) 的值。

    然后 枚举 (k) 的值,可以很快得到 (a^{kx_1}) 的值,然后假如这个值存在于Hash表里,则说明某一个 (x_2) 和它匹配,返回当前的 (x=kx_1-x_2)

    扩展BSGS算法

    求解 (a^xequiv b (mod m))

    namespace exBSGS {
    
        ll qmul(ll a, ll b, ll mod) {
            ll res = 0;
            while(b) {
                if(b & 1)
                    res = (res + a) % mod;
                a = (a + a) % mod, b >>= 1;
            }
            return res;
        }
    
        ll qpow(ll a, ll n, ll m) {
            ll s = 1;
            while(n) {
                if(n & 1)
                    s = qmul(s, a, m);
                a = qmul(a, a, m), n >>= 1;
            }
            return s;
        }
    
        // a^x = b mod m, gcd(b, m) = 1
        ll bsgs(ll a, ll b, ll m, ll k = 1, ll t = 0) {
            static unordered_map<ll, ll> M;
            M.clear();
            if(b == 1)
                return 0;
            ll B = ceil(sqrt(m)), s = b;
            for(ll i = 0; i < B; ++i, s = qmul(s, a, m))
                M[s] = i;
            s = k, k = qpow(a, B, m);
            for(ll i = 1; i <= B; ++i) {
                s = qmul(s, k, m);
                if(M.count(s))
                    // minimum solution
                    return i * B - M[s] + t;
            }
            // no solution
            return -1;
        }
    
        // a^x = b mod m
        ll exbsgs(ll a, ll b, ll m) {
            if(b == 1)
                // minimum solution
                return 0;
            ll k = 1, t = 0;
            for(ll d = __gcd(a, m); d != 1; d = __gcd(a, m)) {
                if(b % d != 0)
                    // no solution
                    return -1;
                ++t, b /= d, m /= d, k = qmul(k, a / d, m);
                if(b == k)
                    // minimum solution
                    return t;
            }
            // minimum solution
            return bsgs(a, b, m, k, t);
        }
    
    }
    

    离散对数

    求解 (x^aequiv b (mod p))

    这里 (p) 是一个质数,众所周知质数都有原根,找出最小的原根 (g)

    有且仅有一个数 (cin[0,p-1)) ,使得 (x=g^c)

    方法一:

    原式变为 ((g^c)^aequiv b (mod p))

    ((g^a)^cequiv b (mod p))

    那么把 (g^a) 视为 (a) ,把 (c) 视为 (x) ,问题就变成了 (a^xequiv b (mod p)) ,使用普通的BSGS算法求解。

    原方程的一个特解是 (xequiv g^c (mod p))

    方法二:
    (x^aequiv b (mod p)) 视作 ((g^c)^aequiv g^t (mod p))

    两边同时取离散对数,得 (caequiv t (mod varphi(p)))

    那么用BSGS求出 (g^t equiv b (mod p))(t) ,然后变成一个线性同余方程问题,用exGCD求解。

    找到所有解:

    上面的方法找到一个特解,那么所有的解是这样找:

    因为 (g^{varphi(p)}equiv 1 (mod p)) (原根的性质)

    那么原方程 (x^aequiv b (mod p))
    ((g^c)^aequiv b (mod p))
    (g^{ca+k*varphi(p)}equiv b (mod p))

    ...

    (forall kin mathbb{Z},xequiv{c+frac{k*varphi(p)}{gcd(a,varphi(p))}} (mod p)) 为通解

    二次剩余就是以上的p为奇质数,a=2的一个特例,但是专门的二次剩余的算法会更快 (O(log p))

    还有p不是质数的情况,晕了。

  • 相关阅读:
    P1121 环状最大两段子段和
    (转)背包9讲
    P1115 最大子段和
    P1108 低价购买
    P1103 书本整理
    P1095 守望者的逃离
    P1091 合唱队形
    P1077 摆花
    hadoop记录topk
    楼天城楼教主的acm心路历程(作为励志用)
  • 原文地址:https://www.cnblogs.com/purinliang/p/13945178.html
Copyright © 2020-2023  润新知