杜教筛 学习笔记
杜教筛用于计算某一类积性函数的前缀和。
思想
构造 Dirchlet 卷积,把一个困难的前缀和转化为两个相对简单的前缀和。
形式化地说,我们有数论函数 $f,g$,记 $F(n) = \sum\limits_{i = 1}^n f(i)$ ,那么有:
$$
\begin{aligned}
\sum\limits_{i = 1}^n fg(i) &= \sum\limits_{i=1}^n \sum_{x\times y = i}f(x)\times g(y) \
&= \sum\limits_{y=1}^n g(y)\sum\limits_{x\times y \leq n} f(x)\
&= \sum\limits_{y=1}^n g(y)\times F(\lfloor \frac{n}{y}\rfloor)\
\end{aligned}
$$
也就是说,我们有:
$$
g(1)F(n) = \sum\limits_{i = 1}^n fg(i) - \sum\limits_{y=2}^n g(y)\times F(\lfloor \frac{n}{y}\rfloor)
$$
这里如果我们假设 $f g$ 的前缀和和 $g$ 的区间和都可以 $O(1)$ 计算(这也是我们应用杜教筛的一个条件),那么计算 $F$,我们需要的就是计算后面 $\sum\limits_{y=2}^n g(y)\times F(\lfloor \frac{n}{y}\rfloor)$ ,那么这个显然可以数论分块,如果直接数论分块,我们*递归计算 $F(\lfloor \frac{n}{y}\rfloor) $就是 $\mathcal{O}(\sqrt n)$ 次的了。
好,我们解决了单次计算的循环次数问题,那么我们发现每次递归的 $F(x)$ 的取值实质上是 $1,2\dots \sqrt n$ ,这个如果直接记忆化暴力计算,通过调和级数我们可以知道复杂度是 $\mathcal{O}(n^\frac{3}{4})$ 的。
但是我们发现,对于较小的 $n$ 通过 $\mathcal{O}\sqrt n$ 来计算是血亏的,我们运用一个类似于根号分治的思想,对于 $1\dots n^c$ 的答案用 $\mathcal{O}(n^c)$ 的时间预处理出来,通过一些积分魔术我们可以得到当 $c = \frac{2}{3}$ 的时候复杂度最优秀,为 $\mathcal{O}(n^{ \frac{2}{3}})$ 。
记忆化的部分,我们可以直接记录一个 ans[x]
代表 $\frac{n}{x}$ 时候的答案。对于计算 $f *g$ 以及 $g$ 的前缀和,我们发现只需要在 $\mathcal{O}(\sqrt n)$ 的时间内算完就不影响复杂度,实际上你也可以套一层杜教筛(
例题
P4213 【模板】杜教筛(Sum)
给定一个正整数,求
$$ans_1=\sum_{i=1}^n\varphi(i)$$
$$ans_2=\sum_{i=1}^n \mu(i)$$
$1 \leq n \lt 2^{31}$
对于 $\varphi$ ,我们有 $\varphi(n) * 1 = id$,这里 $1$ 就是我们的 $g$,$id$ 就是我们的 $f*g$,这两个的求和是非常简单的。
对于 $\mu$,我们有 $\mu(n) * 1 = \epsilon(n) = [n = 1]$,这同样非常容易求和。
参考代码:
1 | const int N = 5e6 + 10; |
P3768 简单的数学题
求
$$\left(\sum_{i=1}^n\sum_{j=1}^n ij \gcd(i,j)\right) \bmod p$$
$n \leq 10^{10}$
$$
\begin{aligned}
&\sum_{i=1}^n\sum_{j=1}^n ij \gcd(i,j)\
&= \sum_{i=1}^n\sum_{j=1}^n\sum_{d=1}^nd ij [\gcd(i,j) = d]\
&= \sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{d=1}^nd^3 ij [\gcd(i,j) = 1]\
&= \sum_{d = 1} ^ n d^3 \sum\limits_{i=1}^{n/d}\sum\limits_{j=1}^{n/d}ij \sum\limits_{k | i,k | j} \mu(k)\
&= \sum_{d = 1} ^ n d^3 \sum\limits_{k} k^2\mu(k) \sum\limits_{i=1}^{n/dk}\sum\limits_{j=1}^{n/dk}ij \
&= \sum_{d = 1} ^ n d^3 \sum\limits_{k} k^2\mu(k) (\sum_{i=1}^{n/dk} i) ^2 \
&\text{Let sum(x)} = \sum\limits_{i=1}^x i,T = dk\
&= \sum_{T=1}^n sum(\frac{n}{T})^2 T^2\sum_{d|T} d\mu(\frac{T}{d})
\end{aligned}
$$
那么我们要求的就是 $T^2\sum_{d|T}d\mu(\frac{T}{d})$,然后我们发现后面这个东西再 Dirchlet 卷积一下有 $\sum_{d|T}d\mu(\frac{T}{d}) = \varphi(T)$,所以就变成了 $T^2\varphi(T)$ ,太神奇啦家人们!
那么我们总的式子就变成了:
$$
\sum_{T=1}^n sum(\frac{n}{T})^2 T^2\varphi(T)
$$
别急,按杜教筛套路继续推下去,我们令 $f(i) = i^2 \varphi(i)$ , $F(i) = \sum\limits_{i=1}^n f(i)$
我们来考虑这个 $f$ 怎么卷比较可做!因为有 $\varphi * 1 = id$,所以我们直接设 $g(x) = x^2$ ,这样我们就易得 $f * g (x) = x ^3$。这就好起来了!所以我们的 $F$ 就好做了:
$$
\begin{aligned}
g(1)F(n) &= \sum\limits_{i = 1}^n f*g(i) -\sum\limits_{i=2}^n g(i)\times F(\lfloor \frac{n}{i}\rfloor) \
F(n) &= \sum\limits_{i=1}^n i^3 - \sum\limits_{i=2}^n i^2 \times F(\lfloor \frac{n}{i}\rfloor)
\end{aligned}
$$
这个是典型的杜教筛式,所以我们就数论分块里面再套一个杜教筛就OK了。
代码:
1 | const int N = 8000000 + 10; |