Loading

BSGS 杂技——平衡复杂度的艺术

大炮请观看最后一部分。

令金牌选手折腰,能轻松战胜 arc div1 中场上无人通过的最后的 \(E\) 题。BSGS 思想已经成为 解决多次询问常系数齐次递推 的新优选?

定义 \(\mathcal{O}(a)-\mathcal{O}(b)\) 表示:一个问题 预处理 复杂度为 \(\mathcal{O}(a)\),单次查询复杂度为 \(\mathcal{O}(b)\)

BSGS 的本质是什么?

是用两个大小为 \(\sqrt n\) 的集合 \(S,T\),此时 \(\{S_i+T_j\}\) 能表示 \(n\) 个信息。

大多数情况 \(S=\{0,1,\cdots,B-1\},T=\{0,B,2B,\cdots,(B-1)B\}\),此时 \(\{S_i+T_j\}=\{0,1,\cdots,B^2-1\}\)

朴素离散对数

最经典的 BSGS 应用。

给定 \(m\ge 2\),定义 \(\log_a x\) 表示最小的 \(k\ge 0\) 使得 \(a^k\equiv x\pmod m\)

此时 \(k\) 的范围(值域)显然是 \([0,M=\varphi(m))\)

\(k\) 分解为 \(pB\,{\color{red}{-}}\,q\),此时 \(a^{pB}\equiv xa^q\pmod m\)

  • 预处理值域内的 \(a^{pB}\),记录到哈希表内。

查询时候枚举 \(q\),看 \(xa^q\bmod m\) 是否在哈希表内出现过。

能做到 \(\mathcal{O}(M/B)-\mathcal{O}(B)\)

假设查询 \(Q\) 次,平衡 \(B=\sqrt{M/Q}\),得复杂度为 \(\mathcal{O}(\sqrt{MQ})\)

生日悖论特殊构造

应用apio2025 T1

这东西其实非常简单。

生日悖论说的是:不断随机非负整数加入集合 \(S\),直到 \(S\) 中出现两个 \(\bmod m\) 同余的数,则 \(|S|\) 期望是 \(\mathcal{O}{\sqrt m}\) 的。

但是若我们要构造集合 \(S\),使得 \(\forall m\in [1,V]\),均存在两个 \(\bmod m\) 同余的数。我们不需要真正随机 \(\mathcal{O}(\sqrt V)\) 个数!

加强的,我们只需要让两两的差 \(S_i-S_j(i\neq j)\) 包含 \(\{1,2,\cdots ,V\}\) 即可。

\(B=\lfloor\sqrt V\rfloor+1\),构造 \(S=\{0,1,\cdots,B-1\ {\color{red}\mid}\ B,2B,\cdots,B^2\}\) 即可,此时 \(S=2B\)

多次询问齐次线性递推远处求值

给定长度为 \(n\) 的线性递推:给定 \(a_{0,2,\cdots,n-1},f_{1,2,\cdots,n},\forall N\ge n:a_N=\sum\limits_{i=1}^{n} f_ia_{N-i}\)

\(q\) 次询问,每次询问 \(m\),给出 \(a_m\) 的值。对 \(\color{red}{10^9+7}\) 取模。

\(1\le n\le 125,1\le q\le 2\times 10^5,1\le m\le 5\times 10^8\)。时限姑且 2s


  • 此算法由 NOI2024 金牌 Doqe 提出。由本博客首次公开。

定义 \(m\) 的值域为 \(V\)。这题能做到 \(\mathcal{O}(\sqrt {Vn\mathbf{M}(n)}+qn)\),其中 \(\mathbf{M}(n)\) 表示 \(\deg =n\) 的多项式乘法复杂度。

由于本题 \(\bmod 10^9+7\),我们一般默认 \(\mathbf{M}(n)=\mathcal{O}(n^2)\)

定义特征多项式 \(f(x)=x^n-\sum\limits_{i=0}^{n-1}f_{n-i}x^{i}\)

考虑 单次齐次线性递推远处求值 等价于做一个多项式快速幂取模 \(r(x)=x^m\bmod f(x),a_m=\sum\limits_{i=0}^{n-1} r_ia_i\)

这样复杂度 \(\mathcal{O}(q\mathbf{M}(n)\log V)\),显然过不去。


朴素 BSGS 是预处理 \(x^{0\sim B-1}\bmod f(x),x^{B,2B,\cdots,B\times\frac{V}{B}}\bmod f(x)\),然后拼起来。

这样复杂度 \(\mathcal{O}((q+\sqrt V)\mathbf{M}(n))\),只少了个 \(\log\),还是过不去。


假设我们取 \(m=kB+r\),此时我们求出 \(R(x)=x^{kB}\bmod f(x)\),那么 \(a_m=\sum\limits_{i=0}^{n-1}R_{i}a_{i+r}\)

相当于 \(a\) 整体平移 \(r\) 项!

于是我们只需求出 \(a\) 的前 \(m+B\) 项,并预处理 \(x^{kB}\bmod f(x)\) 即可。

复杂度 \(\mathcal{O}(\frac{V}{B}\mathbf{M}(n)+Bn)-\mathcal{O}(n)\)

平衡取 \(B=\sqrt{V\mathbf{M}(n)/n}\),得到复杂度为 \(\mathcal{O}(\sqrt {Vn\mathbf{M}(n)}+qn)\)

足以通过此题,感觉这个大炮挺不错的!

应用:ARC 209 E I hate ABC

对于一个 ABC\(S\),定义 \(f(S)\) 为其最长子序列(不一定连续)使得其不存在子序列 ABC 的长度。

\(T\) 组询问,每次给定 \(n,m\),求出所有长度为 \(N\)\(S\)\(f(S)=M\) 的个数。

\(\texttt{Data Range:}\;N-100\le M\le N\le10^6,T\le 2\times 10^5\)

这道题,赛时我的好友 hhoppitree 猜出了当 \(K=N-M\) 固定答案时,答案关于 \(M\) 具有 \(\mathcal{O}(k)\) 阶线性递推式,显然可以在 \(\mathcal{O}(K^4)\) 内对于每个 \(K\)dp 求出前 \(\mathcal{O}(K)\) 项的值以及递推系数,可惜的是,小树并未知晓此算法,因此未通过本题。

在赛后,我向树传授了这个算法,树意识到,如果直接跑这个算法 \(K\) 轮并使用暴力多项式乘法即可做到 \(\mathcal{O}(K^4+N^{1/2}K^{5/2}+TK)\) 的时间复杂度。

而正解的时间复杂度为 \(\mathcal{O}(K^4+N+TK)\),而该做法的时间复杂度不超过正解的 \(\frac{9}{8}\) 次方,几乎无法区分,且该算法能轻易通过原题数据范围。\(\mathbf{record}\)

  • 由此可见,该算法在 OI 中拥有广阔的运用前景!

  • 根据这个应用可以发现,该算法较为固定,常常作为『黑箱』使用。

posted @ 2025-08-03 20:04  HaHeHyt  阅读(174)  评论(1)    收藏  举报