首先我们给道题目:求(sumlimits_{i=1}^nmu(i))
(nleqslant 10^5),我会(O(nsqrt{n}))!
(nleqslant 10^7),我会(O(n))线筛!
(nleqslant 10^9),我……
于是杜教筛就此被发明,它可以在(O(n^{frac{2}{3}}))的时间内求出一些积性函数函数的前缀和,如何做?
假定我们现在要求(S(n)=sumlimits_{i=1}^nf(i)),于是我们找来一个积性函数(g(i))(不知道是什么东西),和(f(i))卷积一下,有
然后我们求一下卷积形式的前缀和
然后我们调整一下枚举顺序,得到
好,我们现在得到(sumlimits_{i=1}^n(f*g)(i)=sumlimits_{d=1}^ng(d)S(lfloordfrac{n}{d} floor)),然后我们把这个先放着,稍微思考一下,显然有如下式子
然后你发现中间一个和我们之前推出来的形式是一样的,于是有
如果中间卷积部分的前缀和非常好算,那么我们就可以对后面那部分进行数论分块,然后递归处理,记得记忆化!
我们回到栗子,题目要求的(f)就是(mu)对吧,代回去有
现在我们需要找一个优秀的(g),使得他们狄利克雷卷积的前缀和非常好算
我们知道
所以((1*mu)=e),你说(e)的前缀和是啥,当然是1啦,于是我们取(g(x)=1),有
然后我们线筛出一部分(mu)的前缀和,再来一波记忆化搜索,做完了
再举个栗子,把(mu)换成(varphi)该怎么做?
因为有
所以还是取(g(x)=1),那么得到
(S(n)=sumlimits_{i=1}^ni-sumlimits_{i=2}^nS(lfloordfrac{n}{i} floor))
等差数列前缀和(O(1))求出就好了
对于不同的(f),只要找到合适的(g),就就可以让你的程序变得非常好写
不会找没关系,打个表解决一切
不过记得不要有事没事想着杜教筛,线筛啥的,埃氏筛法也是很有用的,(O(nln n))枚举倍数也挺好的
骗分过样例,暴力出奇迹
扯了这么多,讲下时间复杂度证明吧
其实可以发现除了(S(n)=sumlimits_{i=2}^nS(lfloordfrac{n}{i} floor))贡献了复杂度外,其他基本上可以(O(1))算出答案(恶心的(g(n))不考虑)
那么我们只要算出(sqrt n)个(S(lfloordfrac{n}{i} floor))的值即可算出(S(n)),于是我们设(T(n))为计算出(S(n))的复杂度,那么有
其中(O(sqrt n))是累加合并的时间
然后我们展开一层,因为更深层的复杂度是高阶小量,所以有
但由于(S(n))本身是可以通过线筛求出一部分的,假定我们预处理了前(k)个的值,且(kgeqslant sqrt n),则复杂度变为
则当(k)取(n^{frac{2}{3}})时可以取到较好的复杂度(T(n)=O(n^{frac{2}{3}}))