目录
杜教筛
我们考虑计算 (displaystyle ans=sum_{i=1}^noldsymbol f(i),nleq 10^9)
这种复杂度,首先,线性筛的复杂度肯定是不够了。我们考虑一个更优秀的方法,杜教筛
杜教筛的条件有三个:
- (oldsymbol f) 为积性函数
- 存在积性函数 (oldsymbol g) 其前缀和能快速计算
- 迪利克雷卷积 (oldsymbol f*oldsymbol g) 能快速计算前缀和
对于满足上述三个条件的 (oldsymbol f,oldsymbol g) ,我们来这么看:
设 (displaystyle F(n)=sum_{i=1}^noldsymbol f(i))
(displaystyle sum_{i=1}^n(oldsymbol f*oldsymbol g)(i)=sum_{i=1}^nsum_{dmid i}oldsymbol f({iover d})oldsymbol g(d)=sum_{d=1}^nsum_{i=1}^n[dmid i]oldsymbol f({iover d})oldsymbol g(d))
(displaystyle herefore sum_{i=1}^n(oldsymbol f*oldsymbol g)(i)=sum_{d=1}^noldsymbol g(d)sum_{i=1}^{n/d}oldsymbol f({idover d})=sum_{d=1}^noldsymbol g(d)sum_{i=1}^{n/d}oldsymbol f(i)=sum_{d=1}^noldsymbol g(d)cdot F(n/d)=sum_{d=2}^noldsymbol g(d)cdot F(n/d)+oldsymbol g(1)cdot F(n))
(displaystyle herefore ans=F(n)=oldsymbol g(1)cdot F(n)=sum_{i=1}^n(oldsymbol f*oldsymbol g)(i)-sum_{d=2}^noldsymbol g(d)cdot F(n/d))
如果满足上述三个条件,则求 (F(n)) 时,(displaystyle sum_{i=1}^n(oldsymbol f*oldsymbol g)(i)) 是可以快速计算的,(oldsymbol g(d)) 也是可以用整出分块优化,并快速计算前缀和的,(F(n/d)) 可以递归求解,又由于 (n/d) 的取值级别为 (sqrt n) ,((n/d)/g=n/gd) 也为 (n/d) 的一种情况
因此,我们可以通过记忆化来优化,最后经过证明,复杂度可以压缩到 (O(n^{3over 4}))
但是还可以更优:
我们预处理 (n^{2over 3}) 范围内的 (F(n)) 值,复杂度即可优化到 (O(n^{2over 3}))
杜教筛的实现
我们整合一下思路:
- 找到符合条件的 (oldsymbol g)
- 筛出 (n^{2over 3}) 范围内的函数前缀和
- 采用记忆化,若 (F(n)) 小于 (n^{2over 3}) 或 (F(n)) 已筛出,则直接返回
- 先算出 (displaystyle sum_{i=1}^n(oldsymbol f*oldsymbol g)(i)) 的值
- 再调用整除分块,实现递归求解