杜教筛
杜教筛用于求一类积性函数的前缀和,时间复杂度可以做到 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)。
方法
设我们要求的是积性函数函数
f
(
x
)
f(x)
f(x) 的前缀和
S
(
n
)
=
∑
i
=
1
n
f
(
i
)
S(n) = \sum_{i = 1}^n f(i)
S(n)=∑i=1nf(i)。
我们取一个积性函数
g
g
g(
g
g
g 具体是什么由
f
f
f 决定,但这不影响推式子)则
∑
i
=
1
n
(
f
∗
g
)
(
i
)
=
∑
i
=
1
n
∑
d
∣
i
g
(
d
)
f
(
i
d
)
=
∑
d
=
1
n
g
(
d
)
∑
d
∣
i
f
(
i
d
)
=
∑
d
=
1
n
g
(
d
)
∑
j
=
1
⌊
n
d
⌋
f
(
j
)
=
∑
d
=
1
n
g
(
d
)
S
(
⌊
n
d
⌋
)
\begin{aligned}\sum_{i = 1}^n (f*g)(i) = &\sum_{i = 1}^n\sum_{d | i} g(d)f\left(\frac{i}{d}\right) \\ = &\sum_{d = 1}^n g(d)\sum_{d | i}f\left(\frac{i}{d}\right) \\ =&\sum_{d = 1}^n g(d)\sum_{j = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(j) \\ =&\sum_{d = 1}^n g(d) S\left(\left\lfloor\frac{n}{d}\right\rfloor\right)\end{aligned}
i=1∑n(f∗g)(i)====i=1∑nd∣i∑g(d)f(di)d=1∑ng(d)d∣i∑f(di)d=1∑ng(d)j=1∑⌊dn⌋f(j)d=1∑ng(d)S(⌊dn⌋) 要求
S
(
n
)
S(n)
S(n),所以尝试计算
g
(
1
)
S
(
n
)
=
∑
d
=
1
n
g
(
d
)
S
(
⌊
n
d
⌋
)
−
∑
d
=
2
n
g
(
d
)
S
(
⌊
n
d
⌋
)
=
∑
i
=
1
n
(
f
∗
g
)
(
i
)
−
∑
d
=
2
n
g
(
d
)
S
(
⌊
n
d
⌋
)
\begin{aligned} g(1)S(n) = &\sum_{d = 1}^n g(d) S\left(\left\lfloor\frac{n}{d}\right\rfloor\right) - \sum_{d = 2}^n g(d) S\left(\left\lfloor\frac{n}{d}\right\rfloor\right) \\ =& \sum_{i = 1}^n (f*g)(i) - \sum_{d = 2}^n g(d) S\left(\left\lfloor\frac{n}{d}\right\rfloor\right) \end{aligned}
g(1)S(n)==d=1∑ng(d)S(⌊dn⌋)−d=2∑ng(d)S(⌊dn⌋)i=1∑n(f∗g)(i)−d=2∑ng(d)S(⌊dn⌋) 也就是说如果
(
f
∗
g
)
(f*g)
(f∗g) 和
g
g
g 的前缀和都能很快地算,后面那个数论分块,我们就可以得到
S
(
n
)
S(n)
S(n) 了!
举例
莫比乌斯函数
f = μ f = \mu f=μ,注意到 μ ∗ 1 = ε \mu*1 = \varepsilon μ∗1=ε, 1 ( x ) = 1 1(x) = 1 1(x)=1 和 ε ( x ) = [ x = 1 ] \varepsilon(x) = [x = 1] ε(x)=[x=1] 的前缀和都很显然,于是取 g = 1 g = 1 g=1 即可。
欧拉函数
f = φ f = \varphi f=φ,注意到 φ ∗ 1 = i \varphi * 1 = i φ∗1=i, 1 ( x ) = 1 1(x) = 1 1(x)=1 和 i ( x ) = x i(x) = x i(x)=x 的前缀和都很显然,于是取 g = 1 g = 1 g=1 即可。
时间复杂度
只考虑 g g g 和 f ∗ g f * g f∗g 的前缀和能够 O ( 1 ) O(1) O(1) 计算的情况。设 T ( n ) T(n) T(n) 为计算 S ( n ) S(n) S(n) 的时间复杂度(大 O O O 记号),有 T ( n ) = O ( n ) + ∑ i = 2 n ( T ( i ) + T ( n i ) ) = O ( n ) + ∑ i = 2 n ( O ( i ) + ∑ j = 2 i T ( j ) + O ( n i ) + ∑ j = 2 n i T ( j ) ) \begin{aligned}T(n) = &O\left(\sqrt n\right) + \sum_{i = 2}^{\sqrt n} \left(T(i) + T\left(\frac{n}{i}\right)\right) \\= &O\left(\sqrt n\right) + \sum_{i = 2}^{\sqrt n}\left(O\left(\sqrt i\right) + \sum_{j = 2}^{\sqrt i} T(j) +O\left(\sqrt{\frac{n}{i}}\right) + \sum_{j = 2}^{\sqrt {\frac{n}{i}}} T(j)\right)\end{aligned} T(n)==O(n)+i=2∑n(T(i)+T(in))O(n)+i=2∑n⎝⎜⎛O(i)+j=2∑iT(j)+O(in)+j=2∑inT(j)⎠⎟⎞ 其中 O ( n ) O\left(\sqrt n\right) O(n) 是该层合并复杂度。
通常用的大 O O O 记号是渐进时间复杂度,可以理解为 n → ∞ n\to \infty n→∞ 的时间消耗,也可以作为最坏时间复杂度理解,因此通常用的大 O O O 记号的定义是:假设程序进行常数运算的次数为 ϕ ( n ) \phi(n) ϕ(n),存在一个函数 τ ( n ) \tau(n) τ(n) 使得 lim n → ∞ ϕ ( n ) τ ( n ) = C \lim\limits_{n\to \infty}\frac{\phi(n)}{\tau(n)} = C n→∞limτ(n)ϕ(n)=C,其中 C C C 是一个 非零 常数,那么该程序时间复杂度为 O ( τ ( n ) ) O(\tau(n)) O(τ(n))。在数学上称 ϕ ( n ) \phi(n) ϕ(n) 和 τ ( n ) \tau(n) τ(n) 是同阶的。
因此从定义可以看出,大 O O O 记号是忽略了高阶无穷小的,只保留同阶无穷。
如果 lim x → ∞ α ( x ) β ( x ) = 0 \lim\limits_{x \to \infty}\frac{\alpha(x)}{\beta(x)} = 0 x→∞limβ(x)α(x)=0,则称 β ( x ) \beta(x) β(x) 比 α ( x ) \alpha(x) α(x) 低阶无穷小;
如果 lim x → ∞ α ( x ) β ( x ) = C ≠ 0 \lim\limits_{x \to \infty}\frac{\alpha(x)}{\beta(x)} = C \neq 0 x→∞limβ(x)α(x)=C=0, C C C 是常数,则称 β ( x ) \beta(x) β(x) 是 α ( x ) \alpha(x) α(x) 的同阶无穷小;
如果 lim x → ∞ α ( x ) β ( x ) = ∞ \lim\limits_{x \to \infty}\frac{\alpha(x)}{\beta(x)} = \infty x→∞limβ(x)α(x)=∞,则称 β ( x ) \beta(x) β(x) 比 α ( x ) \alpha(x) α(x) 高阶无穷小。
由于 lim n → ∞ n 1 2 n 1 4 = lim n → ∞ n 1 4 = ∞ \lim\limits_{n \to \infty}\frac{n^{\frac{1}{2}}}{n^{\frac{1}{4}}} = \lim\limits_{n \to \infty} n^\frac{1}{4} = \infty n→∞limn41n21=n→∞limn41=∞,所以 n \sqrt{\sqrt n} n 相对 n \sqrt n n 是高阶无穷小量,对于大 O O O 记号可以忽略,所以 T ( n ) = O ( n ) + ∑ i = 2 n ( O ( i ) + O ( n i ) ) \begin{aligned}T(n) = &O\left(\sqrt n\right) + \sum_{i = 2}^{\sqrt n}\left(O\left(\sqrt i\right) + O\left(\sqrt{\frac{n}{i}}\right) \right)\end{aligned} T(n)=O(n)+i=2∑n(O(i)+O(in)) (粗略估计)由均值不等式 i + n i ≥ 2 i n i = 2 n 1 4 \sqrt i + \sqrt{\frac{n}{i}} \geq 2\sqrt{\sqrt{i\frac{n}{i}}} = 2n^{\frac{1}{4}} i+in≥2iin=2n41,于是 ∑ i = 2 n ( O ( i ) + O ( n i ) ) ≥ n 1 2 n 1 4 = n 3 4 \sum\limits_{i = 2}^{\sqrt n}\left(O\left(\sqrt i\right) + O\left(\sqrt{\frac{n}{i}}\right) \right) \geq n^{\frac{1}{2}} n^{\frac{1}{4}} = n^{\frac{3}{4}} i=2∑n(O(i)+O(in))≥n21n41=n43,于是 T ( n ) = O ( n 3 4 ) T(n) = O\left(n^{\frac{3}{4}}\right) T(n)=O(n43)。
但是我们可以先线性筛预处理出一部分前缀和,这样某些前缀和就能之间查询了。假设我们预处理了前 m m m 个前缀和,那么复杂度变为 T ( n ) = O ( m ) + O ( n ) + ∑ i = 2 n ( [ i > m ] O ( i ) + [ n i > m ] O ( n i ) ) \begin{aligned} T(n) =&O(m) + O\left(\sqrt n\right) + \sum_{i = 2}^{\sqrt n}\left(\left[\sqrt i > m\right]O\left(\sqrt i\right) + \left[\sqrt{\frac{n}{i}} > m\right]O\left(\sqrt{\frac{n}{i}}\right) \right)\end{aligned} T(n)=O(m)+O(n)+i=2∑n([i>m]O(i)+[in>m]O(in)) 让 m ≥ n 1 4 m \geq n^{\frac{1}{4}} m≥n41(在一定限度内 m m m 肯定越大越好),那么 T ( n ) = O ( m ) + O ( n ) + ∑ i = 2 n [ n i > m ] O ( n i ) = O ( m ) + O ( n ) + ∑ i = 2 n m 2 O ( n i ) ≥ O ( m ) + O ( n ) + O ( n n m 2 ) \begin{aligned} T(n) =&O(m) + O\left(\sqrt n\right) + \sum_{i = 2}^{\sqrt n}\left[\sqrt{\frac{n}{i}} > m\right]O\left(\sqrt{\frac{n}{i}}\right) \\ =&O(m) + O\left(\sqrt n \right) + \sum_{i = 2}^{\frac{n}{m^2}} O\left(\sqrt{\frac{n}{i}}\right)\\ \geq &O(m) + O\left(\sqrt n\right) + O\left(\frac{n\sqrt n}{m^2}\right)\end{aligned} T(n)==≥O(m)+O(n)+i=2∑n[in>m]O(in)O(m)+O(n)+i=2∑m2nO(in)O(m)+O(n)+O(m2nn) 当 m = n 2 3 m = n^{\frac{2}{3}} m=n32 时能取到最优复杂度 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)。
因此杜教筛的时间复杂度为 O ( n 2 3 ) O(n^\frac{2}{3}) O(n32)。