BSGS(Baby-Step-Giant-Step)算法,用来解决 $A^x \equiv B \pmod{C}(0 \leq x < C)$ 这样的问题。
具体讲BSGS算法之前,先介绍一下离散对数。
在整数中,离散对数(英语:Discrete logarithm)是一种基于同余运算和原根的一种对数运算。简单来说,离散对数就是在同余意义下的对数运算。
原始的 $\text{BSGS}$ 要求 $C$ 是素数,拓展 $\text{BSGS}$ 则可以处理 $C$ 不是素数的情形。
$\text{BSGS}$
我们令 $m = \left \lceil \sqrt{C} \right \rceil $ ,那么 $x$ 可以表示为 $i m+j$ 这样的形式,则 $A^x = A^{m^i} A^j$ ,其中 $0\leq i<m$ , $0 \leq j < m$ 。
我们接下来就可以在 $\Theta(\sqrt{C})$ 的时间内枚举 $i$ ,我们令 $D = A^{m^i}$ ,则 $D*A^j \equiv B \pmod{C}$ ,就可以用 $\text{ExtendedGCD}$ 求解出 $A^j$ ,因为 $C$ 是素数,除了 $A$ 是 $C$ 的情况要特判以外总有 $GCD(D, C) = 1$ ,即这个方程总是有解的。
现在我们求出了 $A^j$ ,怎么快速知道 $j$ 的值呢,由于是模 $C$ 意义,所以直接套上对数肯定不合适,那我们可以查表啊!先用 $\Theta(\sqrt{C})$ 的时间内将 $A^k, 0\leq k<m$ 的值全部插进哈希表(想省事的可以考虑一下 $\text{map}$ ,就是复杂度大了点)里面,最后直接 $\Theta(1)$ 查表就可以了。
$\text{ExtendedBSGS}$
$\text{ExtendedBSGS}$ 不要求 $C$ 是素数,主要思想就是约简 $C$ ,使它变成一个素数。
首先,要了解同余有以下性质:
$(k, m) = d$ , $ka \equiv kb \pmod{m}$ $\Rightarrow$ $a \equiv b \pmod{\frac{m}{d}}$
特殊的,$ka \equiv kb \pmod{m} \Rightarrow$ $a \equiv b \pmod{m}$
那么我们就可以来讲如何消去因子了。
我们可以每次消去 $GCD(A, C)$ ,如果 $GCD(A, C)$ 不能整除 $B$ ,那肯定是没有解的.
接下来考虑 $GCD(A, C) \ |\ B$ 的情况。
这样子就给出了单步的计算过程,具体操作就是在 $B$ 和 $C$ 中除掉 $GCD(A, C)$ , 用一个临时变量 $D$ 每次乘 $A / GCD(A, C)$ ,同时用累加器 $cnt$ 每次累加 $1$ ,$A$ 不变。
最后,问题就转化为 $D * A^{x - cnt} \equiv B \pmod{C}$ ,接下来就又是 $BSGS$ 的活儿了。
但是有一点需要注意,在后面的时候我们默认了 $x$ 是大于等于$cnt$ 的,但是很明显 $x < cnt$ 的解也是可能存在的。那么我们只需要在之前做 $\Theta(\log_2C)$ 次枚举排除这种情况就可以了。
$\text{Code}$
哈希就略过了~
1 | //------------------- BSGS --------------------- |