refactor(number-theory/du.md): 修正描述, 补充时间复杂度的推导 (#4767)

* refactor(du.md): correction

* style: format markdown files with remark-lint

* fix(du.md): formula

* fix: links

* fix(du.md): ID -> id

* fix(du.md): formula in analysis of time complexity

* fix(du.md): apply suggestions from code review

Co-authored-by: Nanarikom <46249138+Nanarikom@users.noreply.github.com>

* style(du.md): lint formulas

* refactor(du.md): examples

* feat(du.md): about non-multiplicative function

* refactor: tiny change

* fix: formula

---------

Co-authored-by: 24OI-bot <15963390+24OI-bot@users.noreply.github.com>
Co-authored-by: Nanarikom <46249138+Nanarikom@users.noreply.github.com>
pull/4919/head
Tifa 2023-05-28 11:42:14 +08:00 committed by GitHub
parent ff9b3a43cf
commit a08fad3a68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 157 additions and 118 deletions

View File

@ -1,136 +1,174 @@
author: hsfzLZH1, sshwy, StudyingFather, Marcythm
## 积性函数
杜教筛被用于处理一类数论函数的前缀和问题。对于数论函数 $f$,杜教筛可以在低于线性时间的复杂度内计算 $S(n)=\sum_{i=1}^{n}f(i)$。
在数论题目中,常常需要根据一些 **积性函数** 的性质,求出一些式子的值。
## 算法思想
**积性函数**:对于所有互质的 $a$ 和 $b$,总有 $f(ab)=f(a)f(b)$,则称 $f(x)$ 为积性函数
我们想办法构造一个 $S(n)$ 关于 $S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$ 的递推式
常见的积性函数有:
$d(x)=\sum_{i \mid n} 1$
$\sigma(x)=\sum_{i \mid n} i$
$\varphi(x)=\sum_{i=1}^x 1[\gcd(x,i)=1]$
设 $x = \prod \limits_{i=1} ^ {k} p_i ^ {\alpha_i}$$p_i$ 为质数,
$\mu(x)=\begin{cases}1&\ x=1 \\(-1)^k& \ \forall \alpha_i = 1 \\0 &\ \max\{\alpha_i\}>1\end{cases}$
积性函数有如下性质:
若 $f(x)$$g(x)$ 为积性函数,则
$h(x)=f(x^p)$
$h(x)=f^p(x)$
$h(x)=f(x)g(x)$
$h(x)=\sum_{d \mid x} f(d)g(\frac x d)$
中的 $h(x)$ 也为积性函数。
在莫比乌斯反演的题目中,往往要求出一些数论函数的前缀和,利用 **杜教筛** 可以快速求出这些前缀和。
## 杜教筛
杜教筛被用来处理数论函数的前缀和问题。对于求解一个前缀和,杜教筛可以在低于线性时间的复杂度内求解
对于数论函数 $f$,要求我们计算 $S(n)=\sum_{i=1}^{n}f(i)$.
我们想办法构造一个 $S(n)$ 关于 $S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$ 的递推式
对于任意一个数论函数 $g$,必满足
对于任意一个数论函数 $g$,必满足:
$$
\begin{aligned}
\sum_{i=1}^{n}\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right)&=\sum_{i=1}^{n}g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
\iff
\sum_{i=1}^{n}(f\ast g)(i)&=\sum_{i=1}^{n}g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\sum_{i=1}^{n}(f * g)(i) & =\sum_{i=1}^{n}\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right) \\
& =\sum_{i=1}^{n}g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned}
$$
略证:
其中 $f*g$ 为数论函数 $f$ 和 $g$ 的 [狄利克雷卷积](../poly/dgf.md#dirichlet-%E5%8D%B7%E7%A7%AF)。
$g(d)f\left(\frac{i}{d}\right)$ 就是对所有 $i\leq n$ 的做贡献,因此变换枚举顺序,枚举 $d,\frac{i}{d}$(分别对应新的 $i,j$
???+ note "略证"
$g(d)f\left(\frac{i}{d}\right)$ 就是对所有 $i\leq n$ 的做贡献,因此变换枚举顺序,枚举 $d$,$\frac{i}{d}$(分别对应新的 $i,j$
$$
\begin{aligned}
\sum_{i=1}^n\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right) & =\sum_{i=1}^n\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}g(i)f(j) \\
& =\sum_{i=1}^ng(i)\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}f(j) \\
& =\sum_{i=1}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned}
$$
那么可以得到递推式:
$$
\begin{aligned}
&\sum_{i=1}^n\sum_{d \mid i}g(d)f\left(\frac{i}{d}\right)\\
=&\sum_{i=1}^n\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}g(i)f(j)\\
=&\sum_{i=1}^ng(i)\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}f(j)\\
=&\sum_{i=1}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
g(1)S(n) & = \sum_{i=1}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& = \sum_{i=1}^n (f * g)(i) - \sum_{i=2}^n g(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned}
$$
那么可以得到递推式
假如我们可以构造恰当的数论函数 $g$ 使得:
1. 可以快速计算 $\sum_{i=1}^n(f * g)(i)$
2. 可以快速计算 $g$ 的单点值,以用数论分块求解 $\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$。
则我们可以在较短时间内求得 $g(1)S(n)$。
???+ warning "注意"
无论数论函数 $f$ 是否为积性函数,只要可以构造出恰当的数论函数 $g$, 便都可以考虑用杜教筛求 $f$ 的前缀和。
如考虑 $f(n)=\mathrm{i}\varphi(n)$, 显然 $f$ 不是积性函数,但可取 $g(n)=1$, 从而:
$$
\sum_{k=1}^n (f*g)(k)=\mathrm{i}\frac{n(n+1)}{2}
$$
计算 $\sum_k (f*g)(k)$ 和 $g$ 的时间复杂度均为 $O(1)$, 故可以考虑使用杜教筛。
## 时间复杂度
我们认为计算 $\sum_{i=1}^n(f * g)(i)$ 和 $g(n)$ 的时间复杂度均为 $O(1)$, 设计算 $S(n)$ 的复杂度为 $T(n)$, 此时我们不妨将 $S(n)$ 简化为如下形式:
$$
g(1)S(n)=\sum_{i=1}^n(f\ast g)(i)-\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
S(n)=\sum_{i=2}^n S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
$$
那么假如我们可以快速对 $\sum_{i=1}^n(f \ast g)(i)$ 求和,并用数论分块求解 $\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$ 就可以在较短时间内求得 $g(1)S(n)$.
由 [整除分块/数论分块](./sqrt-decomposition.md) 可知 $\left\lfloor \dfrac n i \right\rfloor$ 共有 $O(\sqrt{n})$ 种取值,故有:
## 问题一
$$
T(n)=O\left(\sqrt{n}\right)+O\left(\sum_{i=2}^{\sqrt{n}} T\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\right)
$$
$$
\begin{aligned}
T\left(\left\lfloor\frac{n}{i}\right\rfloor\right) & =O\left(\sqrt{\frac{n}{i}}\right)+O\left(\sum_{j=2}^{\sqrt{\frac{n}{i}}} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right) \\
& =O\left(\sqrt{\frac{n}{i}}\right)
\end{aligned}
$$
???+ note
$O\left(\sum_{j=2}^{\sqrt{\frac{n}{i}}} T\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\right)$ 视作高阶无穷小,从而可以舍去。
故:
$$
\begin{aligned}
T(n) & =O\left(\sqrt{n}\right)+O\left(\sum_{i=2}^{\sqrt{n}} \sqrt{\frac{n}{i}}\right)=O\left(\sum_{i=2}^{\sqrt{n}} \sqrt{\frac{n}{i}}\right) \\
& =O\left(\int_{0}^{\sqrt{n}}\sqrt{\frac{n}{x}}\mathrm{d}x\right) \\
& =O\left(n^{\frac{3}{4}}\right)
\end{aligned}
$$
如果可以通过线性筛预处理出 $S(1)$ 到 $S(k)$ 的值,此时的 $\sum_i S\left(\left\lfloor \dfrac{n}{i}\right\rfloor\right)$ 中我们只需要计算 $k<\left\lfloor \dfrac{n}{i}\right\rfloor\leq n$ 的部分。设计算这一部分的复杂度为 $T'(n)$,则有:
$$
\begin{aligned}
T'(n) & =O\left(\sum_{i=2}^{\frac{n}{k}} \sqrt{\frac{n}{i}}\right) \\
& =O\left(\int_{0}^{\frac{n}{k}}\sqrt{\frac{n}{x}}\mathrm{d}x\right) \\
& =O\left(\frac{n}{\sqrt{k}}\right)
\end{aligned}
$$
从而:
$$
T(n)=O(k)+T'(n)=O(k)+O\left(\frac{n}{\sqrt{k}}\right)
$$
由均值不等式可知,当 $k=\Theta\left(n^{\frac{2}{3}}\right)$ 时,$T(n)$ 取得最小值 $O\left(n^{\frac{2}{3}}\right)$.
## 例题
### 问题一
???+ note "[P4213【模板】杜教筛Sum](https://www.luogu.com.cn/problem/P4213)"
题目大意:求 $S_1(n)= \sum_{i=1}^{n} \mu(i)$ 和 $S_2(n)= \sum_{i=1}^{n} \varphi(i)$ 的值,$n\le 2^{31} -1$。
求 $S_1(n)= \sum_{i=1}^{n} \mu(i)$ 和 $S_2(n)= \sum_{i=1}^{n} \varphi(i)$ 的值,$1\leq n<2^{31}$.
### 莫比乌斯函数前缀和
=== "莫比乌斯函数前缀和"
**狄利克雷卷积**,我们知道:
我们知道:
$\because \epsilon =\mu \ast 1$$\epsilon(n)=~[n=1]$
$$
\epsilon = [n=1] = \mu * 1 = \sum_{d \mid n} \mu(d)
$$
$\therefore \epsilon (n)=\sum_{d \mid n} \mu(d)$
$$
\begin{aligned}
S_1(n) & =\sum_{i=1}^n \epsilon (i)-\sum_{i=2}^n S_1 \left(\left\lfloor \frac n i \right\rfloor\right) \\
& = 1-\sum_{i=2}^n S_1\left(\left\lfloor \frac n i \right\rfloor\right)
\end{aligned}
$$
$S_1(n)=\sum_{i=1}^n \epsilon (i)-\sum_{i=2}^n S_1(\lfloor \frac n i \rfloor)$
时间复杂度的推导见 [时间复杂度](#时间复杂度) 一节。
$= 1-\sum_{i=2}^n S_1(\lfloor \frac n i \rfloor)$
对于较大的值,需要用 `map` / `unordered_map` 存下其对应的值,方便以后使用时直接使用之前计算的结果。
观察到 $\lfloor \frac n i \rfloor$ 最多只有 $O(\sqrt n)$ 种取值,我们就可以应用 **整除分块**(或称数论分块)来计算每一项的值了。
=== "欧拉函数前缀和"
直接计算的时间复杂度为 $O(n^{\frac 3 4})$。考虑先线性筛预处理出前 $n^{\frac 2 3}$ 项,剩余部分的时间复杂度为
当然也可以用杜教筛求出 $\varphi (x)$ 的前缀和,但是更好的方法是应用莫比乌斯反演。
$O(\int_{0}^{n^{\frac 1 3}} \sqrt{\frac{n}{x}} ~ dx)=O(n^{\frac 2 3})$
对于较大的值,需要用 `map` 存下其对应的值,方便以后使用时直接使用之前计算的结果。
### 欧拉函数前缀和
当然也可以用杜教筛求出 $\varphi (x)$ 的前缀和,但是更好的方法是应用莫比乌斯反演:
$\sum_{i=1}^n \sum_{j=1}^n 1[\gcd(i,j)=1]=\sum_{i=1}^n \sum_{j=1}^n \sum_{d \mid i,d \mid j} \mu(d)$
$=\sum_{d=1}^n \mu(d) {\lfloor \frac n d \rfloor}^2$
由于题目所求的是 $\sum_{i=1}^n \sum_{j=1}^i 1[\gcd(i,j)=1]$,所以我们排除掉 $i=1,j=1$ 的情况,并将结果除以 $2$ 即可。
观察到,只需求出莫比乌斯函数的前缀和,就可以快速计算出欧拉函数的前缀和了。时间复杂度 $O(n^{\frac 2 3})$。
#### 使用杜教筛求解
求 $S(n)=\sum_{i=1}^n\varphi(i)$.
同样的,$\varphi\ast 1=ID$
$$
\begin{aligned}
\sum_{i=1}^n(\varphi\ast 1)(i)&=\sum_{i=1}^n1\cdot S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
\sum_{i=1}^nID(i)&=\sum_{i=1}^n1\cdot S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
\frac{1}{2}n(n+1)&=\sum_{i=1}^nS\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
S(n)&=\frac{1}{2}n(n+1)-\sum_{i=2}^nS\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
\end{aligned}
$$
=== "莫比乌斯反演"
$$
\begin{aligned}
\sum_{i=1}^n \sum_{j=1}^n [\gcd(i,j)=1] & =\sum_{i=1}^n \sum_{j=1}^n \sum_{d \mid i,d \mid j} \mu(d) \\
& =\sum_{d=1}^n \mu(d) {\left\lfloor \frac n d \right\rfloor}^2
\end{aligned}
$$
由于题目所求的是 $\sum_{i=1}^n \sum_{j=1}^i [\gcd(i,j)=1]$, 所以我们排除掉 $i=1,j=1$ 的情况,并将结果除以 $2$ 即可。
观察到,只需求出莫比乌斯函数的前缀和,就可以快速计算出欧拉函数的前缀和了。时间复杂度 $O\left(n^{\frac 2 3}\right)$.
=== "杜教筛"
求 $S(n)=\sum_{i=1}^n\varphi(i)$.
同样的,$\varphi * 1=\operatorname{id}$, 从而:
$$
\begin{aligned}
S(n) & =\sum_{i=1}^n i - \sum_{i=2}^n S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\frac{1}{2}n(n+1) - \sum_{i=2}^n S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
\end{aligned}
$$
??? note "代码实现"
```cpp
--8<-- "docs/math/code/du/du_1.cpp"
```
## 问题二
### 问题二
???+ note "[「LuoguP3768」简单的数学题](https://www.luogu.com.cn/problem/P3768)"
大意:求
@ -139,55 +177,56 @@ $$
\sum_{i=1}^n\sum_{j=1}^ni\cdot j\cdot\gcd(i,j)\pmod p
$$
其中 $n\leq 10^{10},5\times 10^8\leq p\leq 1.1\times 10^9$$p$ 是质数。
其中 $n\leq 10^{10},5\times 10^8\leq p\leq 1.1\times 10^9$,$p$ 是质数。
利用 $\varphi\ast1=ID$ 做莫比乌斯反演化为
利用 $\varphi * 1=\operatorname{id}$ 做莫比乌斯反演化为:
$$
\sum_{d=1}^nF^2\left(\left\lfloor\frac{n}{d}\right\rfloor\right)\cdot d^2\varphi(d)
\left(F(n)=\frac{1}{2}n\left(n+1\right)\right)\\
$$
其中 $F(n)=\frac{1}{2}n(n+1)$
对 $\sum_{d=1}^nF\left(\left\lfloor\frac{n}{d}\right\rfloor\right)^2$ 做数论分块,$d^2\varphi(d)$ 的前缀和用杜教筛处理:
$$
\begin{aligned}
&f(n)=n^2\varphi(n)=(ID^2\varphi)(n)\\
&S(n)=\sum_{i=1}^nf(i)=\sum_{i=1}^n(ID^2\varphi)(i)
\end{aligned}
f(n)=n^2\varphi(n)=(\operatorname{id}^2\varphi)(n)
$$
需要构造积性函数 $g$,使得 $f\times g$ 和 $g$ 能快速求和
单纯的 $\varphi$ 的前缀和可以用 $\varphi\ast1$ 的杜教筛处理,但是这里的 $f$ 多了一个 $ID^2$,那么我们就卷一个 $ID^2$ 上去,让它变成常数:
$$
S(n)=\sum_{i=1}^n\left((ID^2\varphi)\ast ID^2\right)(i)-\sum_{i=2}^nID^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
S(n)=\sum_{i=1}^nf(i)=\sum_{i=1}^n(\operatorname{id}^2\varphi)(i)
$$
化一下卷积
需要构造积性函数 $g$,使得 $f\times g$ 和 $g$ 能快速求和。
单纯的 $\varphi$ 的前缀和可以用 $\varphi * 1$ 的杜教筛处理,但是这里的 $f$ 多了一个 $\operatorname{id}^2$,那么我们就卷一个 $\operatorname{id}^2$ 上去,让它变成常数:
$$
S(n)=\sum_{i=1}^n\left(\left(\operatorname{id}^2\varphi\right) * \operatorname{id}^2\right)(i)-\sum_{i=2}^n\operatorname{id}^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
$$
化一下卷积:
$$
\begin{aligned}
&((ID^2\varphi)\ast ID^2)(i)\\
=&\sum_{d \mid i}(ID^2\varphi)(d)ID^2\left(\frac{i}{d}\right)\\
=&\sum_{d \mid i}d^2\varphi(d)\left(\frac{i}{d}\right)^2\\
=&\sum_{d \mid i}i^2\varphi(d)=i^2\sum_{d \mid i}\varphi(d)\\
=&i^2(\varphi\ast1)(i)=i^3
((\operatorname{id}^2\varphi)* \operatorname{id}^2)(i) & =\sum_{d \mid i}\left(\operatorname{id}^2\varphi\right)(d)\operatorname{id}^2\left(\frac{i}{d}\right) \\
& =\sum_{d \mid i}d^2\varphi(d)\left(\frac{i}{d}\right)^2 \\
& =\sum_{d \mid i}i^2\varphi(d)=i^2\sum_{d \mid i}\varphi(d) \\
& =i^2(\varphi*1)(i)=i^3
\end{aligned}
$$
再化一下 $S(n)$
再化一下 $S(n)$:
$$
\begin{aligned}
S(n)&=\sum_{i=1}^n\left((ID^2\varphi)\ast ID^2\right)(i)-\sum_{i=2}^nID^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
&=\sum_{i=1}^ni^3-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
&=\left(\frac{1}{2}n(n+1)\right)^2-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\
S(n) & =\sum_{i=1}^n\left((\operatorname{id}^2\varphi)* \operatorname{id}^2\right)(i)-\sum_{i=2}^n\operatorname{id}^2(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\sum_{i=1}^ni^3-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
& =\left(\frac{1}{2}n(n+1)\right)^2-\sum_{i=2}^ni^2S\left(\left\lfloor\frac{n}{i}\right\rfloor\right) \\
\end{aligned}
$$
分块求解即可
分块求解即可
??? note "代码实现"
```cpp

View File

@ -2,7 +2,7 @@ author: Early0v0
## 前置知识
- [积性函数](./du.md#积性函数)
- [积性函数](./basic.md#积性函数)
## 定义

View File

@ -10,7 +10,7 @@ $$
\tilde{F}(x) = \sum_{i\ge 1}\frac{f_i}{i^x}
$$
如果序列 $f$ 满足积性(是 [积性函数](../number-theory/du.md#积性函数)$\forall i\perp j, \; f_{ij} = f_i f_j$,那么其 DGF 可以由质数幂处的取值表示:
如果序列 $f$ 满足积性(是 [积性函数](../number-theory/basic.md#积性函数)$\forall i\perp j, \; f_{ij} = f_i f_j$,那么其 DGF 可以由质数幂处的取值表示:
$$
\tilde{F}(x) = \prod_{p\in \mathcal{P}} \left(1 + \frac{f_p}{p^x} + \frac{f_{p^2}}{p^{2x}} + \frac{f_{p^3}}{p^{3x}} + \cdots \right)