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