杜教筛
目录
杜教筛
我们考虑计算 \(\displaystyle ans=\sum_{i=1}^n\boldsymbol f(i),n\leq 10^9\)
这种复杂度,首先,线性筛的复杂度肯定是不够了。我们考虑一个更优秀的方法,杜教筛
杜教筛的条件有三个:
- \(\boldsymbol f\) 为积性函数
- 存在积性函数 \(\boldsymbol g\) 其前缀和能快速计算
- 迪利克雷卷积 \(\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})\)
杜教筛的实现
我们整合一下思路:
- 找到符合条件的 \(\boldsymbol g\)
- 筛出 \(n^{2\over 3}\) 范围内的函数前缀和
- 采用记忆化,若 \(F(n)\) 小于 \(n^{2\over 3}\) 或 \(F(n)\) 已筛出,则直接返回
- 先算出 \(\displaystyle \sum_{i=1}^n(\boldsymbol f*\boldsymbol g)(i)\) 的值
- 再调用整除分块,实现递归求解