Loading

筛法

约定:\(a/b\) 表示 \(\lfloor\frac a b\rfloor\);大写字母表示其对应小写字母所表示的函数的前缀和,例如 \(F(n)=\sum_{i=1}^n f(i)\)\(p_i\) 为第 \(i\) 个质数。

线性筛

适用范围:\(f\) 为积性函数,\(f(p_i^c)\) 的值可快速计算。
功能:\(O(n)\) 计算 \(f\) 的前 \(n\) 个点值。

在做线性筛时同时维护数组 \(low_i\),表示 \(i\) 的最小质因子的最高次幂。

在筛的过程中分类讨论:

  1. \(p_j\nmid i\)\(f_{i\times p_j}=f_i\times f_{p_j}, low_{i\times p_j}=p_j\)
  2. \(i=p_j^c\)\(f_{i\times p_j}\) 直接算,\(low_{i\times p_j}=p_j^{c+1}\)
  3. \(p_j\mid i\land i\neq p_j^c\)\(f_{i\times p_j}=f_{i/low_i}\times f_{p_j\times low_i}, low_{i\times p_j}=low_i\times p_j\)

杜教筛

适用范围:可构造 \(h=f*g\),其中 \(g,h\) 的前缀和都可以快速计算。
功能:\(O(n^{\frac 2 3})\) 算出所有 \(F(n/i)\) 处的点值。(大概的数据范围:\(10^{12}\))。

\[\begin{aligned} \sum_{i=1}^n h(i) &=\sum_{i=1}^n\sum_{d\mid i}g(d)f(i/d) \\ &= \sum_{d=1}^n g(d)\sum_{i=1}^{n/d}f(i) \\ &= \sum_{d=1}^n g(d)F(n/d) \\ &= g(1)F(n) + \sum_{i=2}^n g(i)F(n/i) \end{aligned} \]

\[g(1)F(n) = \left(\sum_{i=1}^n h(i)\right)-\left(\sum_{i=2}^n g(i)F(n/i)\right) \]

预处理前 \(O(n^{\frac 2 3})\) 个点值,利用数论分块递归求值,并且记忆化,可以证明复杂度为 \(O(n^{\frac 2 3})\)
若不预处理则时间复杂度为 \(O(n^{\frac 3 4})\)

例:求 \(\mu\) 的前缀和。构造 \(g=1, h=\epsilon\),则 \(g,h\) 的前缀和都是容易求的。

Min_25 筛

适用范围:\(f(p)\) 可表示为简单的完全积性函数之和,\(f(p^c)\) 的值容易计算。
功能:\(O\left(\dfrac{n^{\frac 3 4}}{\log n}\right) / O(n^{1-\epsilon})\) 筛出 \(F(n)\) 的点值。(大概的数据范围:\(10^{10}\))。

核心思想:将质数逐个筛掉。

第一部分

对于 \(f(p)\) 的每一个完全积性的部分,构造一个函数 \(g\),使得它们在质数处的值一样。则显然 \(g\) 是完全积性的。
\(G(n)=\sum_{i=1}^n g(i)[i\in\mathbf{Prime}]\),我们的目标是求出所有 \(G(n/i)\) 处的点值。

一开始令 \(G(n)=\sum_{i=1}^n g(i)\),然后逐个考虑质数,当筛到第 \(i\) 个质数时:

\[\forall j\ge p_i^2, G(j)\gets G(j) - g(p_i)\left(G(j/p_i)-\sum_{k=1}^{i-1}g(p_k)\right) \]

即我们想让 \(G(j)=\sum_{i=1}^n g(i)[i\in\mathbf{Prime}\lor mnp_i\gt p_i]\)
这个式子表示筛去所有最小质因子恰好为 \(p_i\) 的数,再把形如 \(p_ip_k(k\lt i)\) 这样已经被筛过的数加回来。

容易发现计算过程只需用到 \(G(n/i)\) 的点值,共 \(O(\sqrt n)\) 个,离散化后可以存下。
这部分时间复杂度 \(O\left(\dfrac{n^{\frac 3 4}}{\log n}\right)\)

第二部分

\(F(i,n)\) 为最小质因子大于等于 \(p_i\) 的答案,有递推式:

\[F(i,n)\gets G(n)-\left(\sum_{j=1}^{i-1}f(p_j)\right)+\sum_{k\ge i,p_k^{c+1}\le n}f(p_k^c)F(k+1,n/p_k^c)+f(p_k^{c+1}) \]

这个式子前两项是质数部分,后面的是合数部分,其中形如 \(p_k^c(c\ge 2)\) 的部分需要特殊处理,因为 \(F(k+1,\dots)\) 显然不包括这部分。

直接暴搜即可,无需记忆化,边界条件显然是当 \(p_i\gt n\) 时,\(F(i,n)=0\)
这部分时间复杂度 \(O(n^{1-\epsilon})\)

最后 \(F(1,n)+1\) 即为答案,因为 \(f(1)\) 要特殊处理。

posted @ 2024-10-31 22:03  Accelessar  阅读(2)  评论(0)    收藏  举报