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不是质数的情况,晕了。