杜教筛

目录

目录地址

上一篇

下一篇


杜教筛

我们考虑计算 \(\displaystyle ans=\sum_{i=1}^n\boldsymbol f(i),n\leq 10^9\)

这种复杂度,首先,线性筛的复杂度肯定是不够了。我们考虑一个更优秀的方法,杜教筛

杜教筛的条件有三个:

  1. \(\boldsymbol f\) 为积性函数
  2. 存在积性函数 \(\boldsymbol g\) 其前缀和能快速计算
  3. 迪利克雷卷积 \(\boldsymbol f*\boldsymbol g\) 能快速计算前缀和

对于满足上述三个条件的 \(\boldsymbol f,\boldsymbol g\) ,我们来这么看:

\(\displaystyle F(n)=\sum_{i=1}^n\boldsymbol f(i)\)

\(\displaystyle \sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)=\sum_{i=1}^n\sum_{d\mid i}\boldsymbol f({i\over d})\boldsymbol g(d)=\sum_{d=1}^n\sum_{i=1}^n[d\mid i]\boldsymbol f({i\over d})\boldsymbol g(d)\)

\(\displaystyle \therefore \sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)=\sum_{d=1}^n\boldsymbol g(d)\sum_{i=1}^{n/d}\boldsymbol f({id\over d})=\sum_{d=1}^n\boldsymbol g(d)\sum_{i=1}^{n/d}\boldsymbol f(i)=\sum_{d=1}^n\boldsymbol g(d)\cdot F(n/d)=\sum_{d=2}^n\boldsymbol g(d)\cdot F(n/d)+\boldsymbol g(1)\cdot F(n)\)

\(\displaystyle \therefore ans=F(n)=\boldsymbol g(1)\cdot F(n)=\sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)-\sum_{d=2}^n\boldsymbol g(d)\cdot F(n/d)\)

如果满足上述三个条件,则求 \(F(n)\) 时,\(\displaystyle \sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)\) 是可以快速计算的,\(\boldsymbol g(d)\) 也是可以用整出分块优化,并快速计算前缀和的,\(F(n/d)\) 可以递归求解,又由于 \(n/d\) 的取值级别为 \(\sqrt n\)\((n/d)/g=n/gd\) 也为 \(n/d\) 的一种情况

因此,我们可以通过记忆化来优化,最后经过证明,复杂度可以压缩到 \(O(n^{3\over 4})\)

但是还可以更优:

我们预处理 \(n^{2\over 3}\) 范围内的 \(F(n)\) 值,复杂度即可优化到 \(O(n^{2\over 3})\)


杜教筛的实现

我们整合一下思路:

  1. 找到符合条件的 \(\boldsymbol g\)
  2. 筛出 \(n^{2\over 3}\) 范围内的函数前缀和
  3. 采用记忆化,若 \(F(n)\) 小于 \(n^{2\over 3}\)\(F(n)\) 已筛出,则直接返回
  4. 先算出 \(\displaystyle \sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)\) 的值
  5. 再调用整除分块,实现递归求解
posted @ 2020-03-17 09:54  JustinRochester  阅读(216)  评论(0编辑  收藏  举报