首先我们给道题目:求n∑i=1μ(i)
n⩽105,我会O(n√n)!
n⩽107,我会O(n)线筛!
n⩽109,我……
于是杜教筛就此被发明,它可以在O(n23)的时间内求出一些积性函数函数的前缀和,如何做?
假定我们现在要求S(n)=n∑i=1f(i),于是我们找来一个积性函数g(i)(不知道是什么东西),和f(i)卷积一下,有
(f∗g)(n)=∑d|ng(d)f(nd)
然后我们求一下卷积形式的前缀和
n∑i=1(f∗g)(i)=n∑i=1∑d|ig(d)f(id)
然后我们调整一下枚举顺序,得到
n∑d=1g(d)∑d|if(id)
n∑d=1g(d)⌊nd⌋∑i=1f(i)
n∑d=1g(d)S(⌊nd⌋)
好,我们现在得到n∑i=1(f∗g)(i)=n∑d=1g(d)S(⌊nd⌋),然后我们把这个先放着,稍微思考一下,显然有如下式子
g(1)S(n)=n∑i=1g(i)S(⌊ni⌋)−n∑i=2g(i)S(⌊ni⌋)
然后你发现中间一个和我们之前推出来的形式是一样的,于是有
g(1)S(n)=n∑i=1(f∗g)(i)−n∑i=2g(i)S(⌊ni⌋)
如果中间卷积部分的前缀和非常好算,那么我们就可以对后面那部分进行数论分块,然后递归处理,记得记忆化!
我们回到栗子,题目要求的f就是μ对吧,代回去有
g(1)S(n)=n∑i=1(μ∗g)(i)−n∑i=2g(i)S(⌊ni⌋)
现在我们需要找一个优秀的g,使得他们狄利克雷卷积的前缀和非常好算
我们知道
∑d|nμ(d)=[n=1]=e
所以(1∗μ)=e,你说e的前缀和是啥,当然是1啦,于是我们取g(x)=1,有
S(n)=1−n∑i=2S(⌊ni⌋)
然后我们线筛出一部分μ的前缀和,再来一波记忆化搜索,做完了
再举个栗子,把μ换成φ该怎么做?
因为有
∑d|nφ(d)=i=id(i)
所以还是取g(x)=1,那么得到
S(n)=n∑i=1i−n∑i=2S(⌊ni⌋)
等差数列前缀和O(1)求出就好了
对于不同的f,只要找到合适的g,就就可以让你的程序变得非常好写
不会找没关系,打个表解决一切
不过记得不要有事没事想着杜教筛,线筛啥的,埃氏筛法也是很有用的,O(nlnn)枚举倍数也挺好的
骗分过样例,暴力出奇迹
扯了这么多,讲下时间复杂度证明吧
其实可以发现除了S(n)=n∑i=2S(⌊ni⌋)贡献了复杂度外,其他基本上可以O(1)算出答案(恶心的g(n)不考虑)
那么我们只要算出√n个S(⌊ni⌋)的值即可算出S(n),于是我们设T(n)为计算出S(n)的复杂度,那么有
T(n)=O(√n)+√n∑i=1(T(i)+T(ni))
其中O(√n)是累加合并的时间
然后我们展开一层,因为更深层的复杂度是高阶小量,所以有
T(n)=√n∑i=1O(√i)+O(√ni)=O(n34)
但由于S(n)本身是可以通过线筛求出一部分的,假定我们预处理了前k个的值,且k⩾√n,则复杂度变为
T(n)=nk∑i=1√ni=O(n√k)
则当k取n23时可以取到较好的复杂度T(n)=O(n23)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!