basic
BSGS算法英文名叫“baby-step giant-step”,又称“大步小步算法”。
这个算法听名字似乎是个随机化算法,但实际上是数论算法。
具体地,这个算法解决的是 $a^x \equiv b \pmod{p}$ 的解,其中 $a$、$b$、$p$ 是已知的($0 \leq a,b<p$,保证 $\gcd(a,p)=1$),$x$ 是要求的。
这个算法甚至可以求出所有的 $x$,但为了好讲,我们先考虑如何求出是否有解,以下代码中YES
就代表确定有解了。
force algorithm
首先,有一个暴力算法:
rep(x, 0, INF)
if(ksm(a, x, p) == b)
YES
但这个算法是 $O(\infty)$ 的,我们考虑优化。
optimization algorithm 1
我们考虑 $x$ 的上界,根据欧拉定理,$a^{\varphi(p)} \equiv 1 \pmod{p}$,我们就可以确定,$x$ 的上界就是 $\varphi(p)$(准确来说减 $1$ 也彳亍),因为如果 $x>\varphi(p)$,那么 $a^x$ 就等于 $a^{x-\varphi(p)}$,也就成为了一个循环,所以上界就是 $\varphi(p)$。
由于 $\varphi(p)<p$,所以可以把 $p$ 当做是质数,$x$ 的上界也就是 $p-1$ 了。
所以:
rep(x, 0, p - 1)
if(ksm(a, x, p) == b)
YES
optimization algorithm 2 (BSGS)
但这个算法还是可能会TLE,我们继续考虑优化
我们定义 $q=\left\lceil \sqrt{p} \right\rceil$,那么我们其实就可以把 $x$ 表示为 $q$ 进制下的两位数,具体地,我们把 $x$ 表示为了 $Aq+B$($0 \leq A,B<q$),然后上述公式就可以化成 $a^{Aq+B} \equiv b \pmod{p}$,即 $a^{Aq} \times a^B \equiv b \pmod{p}$。
但此时仍然不好求答案,我们继续转化,我们考虑移项,变成 $a^{Aq} \equiv b \times a^{-B} \pmod{p}$。
但这个 $a^{-B}$ 不好看,我们换一下。
我们从最初公式开始修改:
$a^{Aq-B} \equiv b \pmod{p}$($0 \leq A \leq q \land 0 \leq B<q$)
变化后:
$a^{Aq} \times a^{-B} \equiv b \pmod{p}$
移项后:
$a^{Aq} \equiv b \times a^B \pmod{p}$
但此时我们发现还是没有显著优化效果啊,代码还是 $O(p)$ 的:
rep(A, 0, q)
rep(B, 0, q - 1)
if(ksm(a, A * q, p) == b * ksm(a, B, p) % p)
YES
但我们发现,两重循环枚举的 $A$ 和 $B$ 是独立的,我们可以使用类似于双向搜索的思想变化成:
set<LL> s;
rep(A, 0, q)
s.insert(ksm(a, A * q, p));
rep(B, 0, q - 1)
if(s.count(b * ksm(a, B, p) % p))
YES
所以这个算法复杂度就变成了 $O(q \times \log q)$,即 $O(\sqrt{p} \times \log \sqrt{p})$,在 $p \leq 2 \times 10^9$ 左右的数据范围下是稳稳地过的。
summary and exdend
其实BSGS就是用的(类似于)拆分的方法,把 $x$ 拆成用两个数 $A$、$B$($A,B$ 在根号范围)来表示,然后发现 $A$ 和 $B$ 的枚举独立,然后才有这个优化。
最开始的时候,提到有求出所有的 $x$ 的方法,其实也就是小改动一下,把set<LL>
换成map<LL,bs<LL>>
即可,代码很相似。
不过,让求出所有的 $x$ 的题目必须要保证解的数量,但求出 $x$ 的数量的题目就不需要,对于求数量的题目,要换成map<LL,LL>
来存。
exBSGS
上面说要保证 $\gcd(a,p)=1$,但如果不保证呢?就需要用到exBSGS。
其实exBSGS也很简单,首先我们设 $d=\gcd(a,p)$,那么显然在 $d|b$ 的时候,方程才有解。
然后我们考虑转化。
我们把方程直接转化为 $\dfrac{a^x}{d} \equiv \dfrac{b}{d} ~ \left( \bmod~\dfrac{p}{d} \right)$,即 $\dfrac{a}{d} \times a^{x-1} \equiv \dfrac{b}{d} ~ \left( \bmod~\dfrac{p}{d} \right)$。
但此时的 $a$ 和 $\dfrac{p}{d}$ 也不一定互质,我们需要继续进行操作。
我们设进行了 $k$ 次操作,第 $i$ 次操作前,$d$ 的值为 $d_i$,那么其实最终的方程就是:
$\dfrac{a^k}{d_1 \times d_2 \times d_3 \times \dots \times d_k} \times a^{x-k} \equiv \dfrac{b}{d_1 \times d_2 \times d_3 \times \dots \times d_k} ~ \left( \bmod~\dfrac{p}{d_1 \times d_2 \times d_3 \times \dots \times d_k} \right)$。
此时直接用类似于BSGS的方法求即可。