浅谈算法——杜教筛

首先我们给道题目:求i=1nμ(i)

n105,我会O(nn)

n107,我会O(n)线筛!

n109,我……

于是杜教筛就此被发明,它可以在O(n23)的时间内求出一些积性函数函数的前缀和,如何做?

假定我们现在要求S(n)=i=1nf(i),于是我们找来一个积性函数g(i)(不知道是什么东西),和f(i)卷积一下,有

(fg)(n)=d|ng(d)f(nd)

然后我们求一下卷积形式的前缀和

i=1n(fg)(i)=i=1nd|ig(d)f(id)

然后我们调整一下枚举顺序,得到

d=1ng(d)d|if(id)

d=1ng(d)i=1ndf(i)

d=1ng(d)S(nd)

好,我们现在得到i=1n(fg)(i)=d=1ng(d)S(nd),然后我们把这个先放着,稍微思考一下,显然有如下式子

g(1)S(n)=i=1ng(i)S(ni)i=2ng(i)S(ni)

然后你发现中间一个和我们之前推出来的形式是一样的,于是有

g(1)S(n)=i=1n(fg)(i)i=2ng(i)S(ni)

如果中间卷积部分的前缀和非常好算,那么我们就可以对后面那部分进行数论分块,然后递归处理,记得记忆化!

我们回到栗子,题目要求的f就是μ对吧,代回去有

g(1)S(n)=i=1n(μg)(i)i=2ng(i)S(ni)

现在我们需要找一个优秀的g,使得他们狄利克雷卷积的前缀和非常好算

我们知道

d|nμ(d)=[n=1]=e

所以(1μ)=e,你说e的前缀和是啥,当然是1啦,于是我们取g(x)=1,有

S(n)=1i=2nS(ni)

然后我们线筛出一部分μ的前缀和,再来一波记忆化搜索,做完了


再举个栗子,把μ换成φ该怎么做?

因为有

d|nφ(d)=i=id(i)

所以还是取g(x)=1,那么得到

S(n)=i=1nii=2nS(ni)

等差数列前缀和O(1)求出就好了

对于不同的f,只要找到合适的g,就就可以让你的程序变得非常好写

不会找没关系,打个表解决一切

不过记得不要有事没事想着杜教筛,线筛啥的,埃氏筛法也是很有用的,O(nlnn)枚举倍数也挺好的

骗分过样例,暴力出奇迹


扯了这么多,讲下时间复杂度证明吧

其实可以发现除了S(n)=i=2nS(ni)贡献了复杂度外,其他基本上可以O(1)算出答案(恶心的g(n)不考虑)

那么我们只要算出nS(ni)的值即可算出S(n),于是我们设T(n)为计算出S(n)的复杂度,那么有

T(n)=O(n)+i=1n(T(i)+T(ni))

其中O(n)是累加合并的时间

然后我们展开一层,因为更深层的复杂度是高阶小量,所以有

T(n)=i=1nO(i)+O(ni)=O(n34)

但由于S(n)本身是可以通过线筛求出一部分的,假定我们预处理了前k个的值,且kn,则复杂度变为

T(n)=i=1nkni=O(nk)

则当kn23时可以取到较好的复杂度T(n)=O(n23)

posted @   Wolfycz  阅读(1898)  评论(1编辑  收藏  举报
编辑推荐:
· 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框架的用法!
点击右上角即可分享
微信分享提示