杜教筛

杜教筛用于快速求一类数论函数前缀和,形式化的:杜教筛可以低复杂度求 \(F(n) = \sum\limits_{i=1}^n f(i)\)

算法思想

杜教筛的核心思想在于构建 \(F(n)\)\(F(\lfloor\dfrac{n}{i}\rfloor)\) 的递推关系。

对于任意数论函数 \(g\),记 \(h = f * g\),都有:

\[\begin{align*} H(n) = \sum\limits_{i \le n}h(i) &= \sum\limits_{i \le n} \sum_{d | i} f(d) g(\frac{n}{d}) \\ &= \sum\limits_{i \le n} g(i) S(\lfloor \frac{n}{i} \rfloor) \end{align*} \]

证明考虑只有 \(ij \le n\)\(f(j)\)\(g(i)\) 有贡献。

移项后不难写出递推式:

\[S(n)g(1) = \sum_{i = 1}^n (f * g)(i) - \sum\limits_{i = 2}^n g(i)S(\lfloor \frac{n}{i} \rfloor) \]

这说明如果 \(g, h\) 的前缀和好求,那我们就可以通过数论分块加速计算 \(F(n)\)

时间复杂度

一个简单的引理 \(\lfloor \dfrac{n}{ab} \rfloor = \lfloor \dfrac{\lfloor \frac{n}{a} \rfloor}{b} \rfloor\),由此我们意识到,有用的 \(S\) 点值集合一定是 \(\{x \mid \exists \ i, \lfloor \dfrac{n}{i} \rfloor = x\}\) 的子集。

假设我们按从小到大的顺序递推或使用记忆化来实现的话,我们可以假设所有在递推式中用到的值都可以 \(\mathcal O(1)\) 计算,于是类似整除分块我们可以写出:

\[T(n) = \sum\limits_{i \le \sqrt n} \mathcal O(\sqrt i) + \mathcal O(\sqrt{\lfloor \dfrac{n}{i} \rfloor}) \le \mathcal O(\displaystyle\int_1^{\sqrt n} (\sqrt x + \sqrt{\dfrac{n}{x}}) \mathrm{d}x) \approx \mathcal O(n^{3 / 4}) \]

但是我们发现在第一部分的计算中,我们在及其稠密的点值区间中任然采用了复杂度较高的计算方式,我们考虑分块优化。具体的,找到阈值 \(B > \sqrt n\),我们对 \(\le B\) 的部分用线性筛求解,而对大于的部分使用递推的方式解决,则复杂度为:

\[\begin{align*} T^\prime(n) &= \mathcal O(B) + \sum\limits_{\frac{n}{i} > B} \mathcal O(\sqrt{\dfrac{n}{i}}) \\ &= \mathcal O(B) + \sum\limits_{i < \frac{n}{B}} \mathcal O(\sqrt{\dfrac{n}{i}}) \\ &\le \mathcal O(B) + \displaystyle \int_1^{\frac{n}{B}} \mathcal O(\sqrt{\dfrac{n}{x}}) \mathrm{d}x \\ &\approx \mathcal O(B) + \mathcal O(\dfrac{n}{\sqrt B}) \end{align*} \]

通过均值不等式,不难发现最小值取在 \(B = \mathcal O(n^{2 / 3})\),此时总复杂度为 \(\mathcal O(n^{2 / 3})\)

UPD

\(2024.6.17\) 日,修复了 \(\LaTeX\) 和复杂度证明。

posted @ 2023-07-17 21:27  JWRuixi  阅读(44)  评论(0)    收藏  举报