题目

找到最小的 xx 使得 ax≡b(modp)a^x \equiv b \pmod{p}。

我们不妨想象一个巨大的操场,其上等距排列着从 00 到 p−1p - 1 的 pp 个位置,起始时我们站在位置 11(单位元)。xx 从 00 开始,每增加 11,我们就从现在的位置 rr 前进一次 到 ar mod par \bmod p;该过程将始终进行,直到在前进 xx 次后,我们停在了位置 bb 上。最暴力的方法即为枚举,但对于大多数题目而言,pp 的值通常很大,在大的操场上枚举是较为困难的。

BSGS 算法可以解决这样的问题。假如现在我们向操场派出两个人,Baby-Step 和 Giant-Step,让他们帮助我们完成在操场上行走。值得注意的是,两个人的行走策略有所差异:Baby-Step 每次行动仅前进一次,但 Giant-Step 每次行动可前进多次。 我们让 Baby-Step 和 Giant-Step 分别从终点和起点出发,他们在操场上各自前进;当他们相遇的时候,我们取 Giant-Step 从起点到相遇点的前进次数和 Baby-Step 从终点到相遇点的前进次数,只需对两者作差,即得到我们从起点到终点需要前进的次数,并可以以此推导出答案。

这里,我们将总前进次数 xx 分为

x=i⋅m−jx = i \cdot m - j

其中,ii 表示 Giant-Step 的行动次数,mm 表示 Giant-Step 的一次行动前进多少次,jj 表示 Baby-Step 的前进次数。通常取 mm 为 ⌈p⌉\lceil \sqrt{p} \rceil。我们将上述式子先代入原方程中,有

ai⋅m−j≡b(modp)a^{i \cdot m - j} \equiv b \pmod{p}

在同余式两边同乘以 aja^j,得

(am)i≡b⋅aj(modp)(a^m)^i \equiv b \cdot a^j \pmod{p}

这个式子是算法的核心。同余式左侧 (am)i(a^m)^i 显示了 Giant-Step 的行动,右侧 b⋅ajb \cdot a^j 显示了 Baby-Step 的行动。

在继续之前,我们需要说明一个前提:以下默认 gcd⁡(a,p)=1\gcd(a, p) = 1。在多数题目中 pp 为素数且 aa 不是 pp 的倍数,因此这个条件自然成立。该条件保证了 aja^j 在模 pp 下可逆,从而可以从右侧等式反推出原来的 xx。

另外,如果 b≡1(modp)b \equiv 1 \pmod{p},显然 x=0x = 0 就是最小解,因此实现时应先特判并直接返回 00。

下面描述具体过程。

对于 Baby-Step,起初站在终点 bb 上,并使用一张哈希表记录着其前进的全过程:前进 00 次时,记录「前进 00 次到达了 b⋅a0 mod pb \cdot a^0 \bmod p」;前进 11 次时,记录「前进 11 次到达了 b⋅a1 mod pb \cdot a^1 \bmod p」……Baby-Step 一直如此前进直到 (m−1)(m - 1) 次,将这 mm 对「前进次数—到达位置」的关系全部记录在了一张哈希表里。现在,这个哈希表则类似于一张地图,它记录了从终点 bb 出发,前进不到 mm 次,即 00 到 m−1m-1 次能到达的所有位置。若同一个位置被多次到达,实现时应保留更大的 jj,以保证最终得到的 x=im−jx = im - j 尽可能小。

下面,我们让 Giant-Step 出发,站在起点 11 上。行动 11 次(前进 mm 次)时,Giant-Step 对照哈希表以检验自己现在所处的位置 (am)1 mod p(a^m)^1 \bmod p 是否位于哈希表内:如果有,则停止;如果否,则继续行动 11 次。Giant-Step 将一直行动,直到第 ii 次行动时,其处于的位置 (am)i mod p(a^m)^i \bmod p 恰好位于哈希表内。这样,我们便知道了:Giant-Step 从起点 11 出发,行动 ii 次(前进 imim 次)后到达了相遇点;Baby-Step 从终点 bb 出发,前进 jj 次后也到达了相遇点。因此,若我们从起点出发,只需前进

x=i⋅m−jx = i \cdot m - j

次即可到达终点。

由于 m=⌈p⌉m = \lceil \sqrt{p} \rceil,任意可能的 x<px < p 都可以写成 x=im−jx = im - j 的形式,其中 1≤i≤m1 \le i \le m,0≤j<m0 \le j < m。因此 Giant-Step 至多行动 mm 次,Baby-Step 也至多记录 mm 条哈希表,所以算法总复杂度为 O(p)O(\sqrt{p}) 的时间和 O(p)O(\sqrt{p}) 的空间。在 MoeCTF 2025 的这道 ezBSGS 题目 中,pp 的值大约为 101410^{14},但 p\sqrt{p} 的值仅为 10710^7,可以认为 BSGS 算法是容易计算的。