杜教筛可以用来在非线性时间内求一个积性函数的前缀和,即 S(n)=∑ni=1f(i)
前置知识#
积性函数#
积性函数:若有数论函数f对于任意互质整数a,b都有f(a⋅b)=f(a)⋅f(b),则f为积性函数。
完全积性函数:对于任意整数a,b有 f(a⋅b)=f(a)⋅f(b)的数论函数。
这里列举一些常见的:
-
积性函数:φ,μ,σ,d
-
完全积性函数:ϵ,I,id
狄利克雷卷积#
设 f,g 是两个数论函数,它们的狄利克雷卷积是:
(f⋅g)(n)=∑d|nf(d)⋅g(nd)
它满足交换律、结合律、分配律
单位元是ϵ,即f⋅ϵ=f
这里有几个常用的等式:
μ⋅I=ϵφ⋅I=idμ⋅id=φ
整除分块#
很多反演题目都会有一个这样的形式:∑ni=1⌊ni⌋
对于这个式子,我们可以朴素地进行O(N)的计算。但是很多情况下,这种做法的复杂度是不被允许的。
我们对于每一个n进行打表,发现有大量的值是重复的,而每一个值按顺序排布,呈块状形式,并且每一块的末尾为⌊n⌊ni⌋⌋。至此,我们就可以在O(√N)的时间内进行计算。
但是上式经常会乘上一些积性函数,这时就可以对积性函数求一个前缀和,每一次跳块也就相当于跳过了这一整段的函数和。
一般的整除分块形式:
for (int l=1,r=0; l<=n; l=r+1) {
r=n / (n / l);
}
莫比乌斯反演#
若有
F(n)=∑d∣nf(d)
则
f(n)=∑d∣nμ(d)⋅F(nd)=∑d∣nμ(nd)⋅F(d)
证明:#
我们用狄利克雷卷积来表示上面的式子,得到F=f⋅I
将F卷上μ得到
F⋅μ=f⋅I⋅μF⋅μ=f⋅(I⋅μ)=f⋅ϵ=ff=F⋅μ
代入狄利克雷卷积原式:
f(n)=∑d∣nμ(d)⋅F(nd)=∑d∣nμ(nd)⋅F(d)
证毕。
给定n,求
n∑i=1n∑j=1gcd(i,j)
欧拉函数有一个性质:∑d∣nφ(d)=n
于是我们可以将原式子套路一下:
n∑i=1n∑j=1gcd(i,j)=n∑i=1n∑j=1∑d∣gcd(i,j)φ(d)=n∑i=1n∑j=1∑d∣i,d∣jφ(d)
把d提到前面去:
=n∑d=1⌊nd⌋∑i=1⌊nd⌋∑j=1φ(d)=n∑d=1φ(d)⋅⌊nd⌋⋅⌊nd⌋
这样就可以做了。可以用欧拉筛筛出欧拉函数的前缀和,使用整除分块进行优化。
给定n,m,求
n∑i=1m∑j=1[gcd(i,j)∈Prime]
我们不知道gcd(i,j)是多少,所以我们枚举它(这里假定n⩽m):
n∑p∈Primen∑i=1m∑j=1[gcd(i,j)=p]
同时除以k得到
n∑p∈Prime⌊np⌋∑i=1⌊mp⌋∑j=1[gcd(i,j)=1]
利用一下μ的性质:∑d∣nμ(d)=[n=1]
像上一题那样,把后面替换掉:
n∑p∈Prime⌊np⌋∑i=1⌊mp⌋∑j=1∑d∣gcd(i,j)μ(d)
枚举d,把d提到前面。因为d∣gcd(i,j),所以i,j是d的倍数,把它们上限全都除上d,后面再乘回去,发现个数可直接求,所以去掉两个求和:
n∑p∈Prime⌊np⌋∑d=1μ(d)⋅⌊npd⌋⋅⌊mpd⌋
但是这样的复杂度还是过不去。我们继续优化:设T=p⋅d,枚举T,再次提到前面去:
n∑T=1∑p∣T,p∈Prime⌊nT⌋⋅⌊mT⌋⋅μ(Tp)
而后面还是可以预处理+整除分块进行优化。
杜教筛#
一般式#
我们要求∑ni=1f(i)
用狄利克雷卷积,设有积性函数F,g满足F=f⋅g,记S(n)为上式。如果说我们的F,g都是很容易求的函数,那么我们就可以用它们来求f。那么,我们推一下F的前缀和:
n∑i=1F(i)=n∑i=1∑d|ng(d)⋅f(nd)=n∑d=1g(d)⋅⌊nd⌋∑i=1f(i)=n∑d=1g(d)⋅S(nd)
我们要求的是S(n),所以我们从右式中拆一个出来,即把i=1单独考虑:
n∑i=1F(i)=g(1)⋅S(n)+n∑d=2g(d)⋅S(nd)g(1)⋅S(n)=n∑i=1F(i)−n∑d=2g(d)⋅S(nd)
这就是杜教筛的一般式。
复杂度证明#
首先给出杜教筛的复杂度:
Θ(√n∑i=0√i+√n∑i=0√ni)
积分求近似:
Θ(√n∑i=0√i+√n∑i=0√ni)=Θ(∫√n0(√x)dx+∫√n0(√n√x)dx)=Θ(23√n32+√n⋅2√n12)=Θ(n34)
如果我们预处理前 k 的部分,则可以优化复杂度。当 k=n23 时有理论最优复杂度:
Θ(k+nk∑i=0√ni)=Θ(k+∫nk0√nxdx)=Θ(k+2√n√nk)=Θ(k+2nk−12)⩾Θ(2√2nk12)
最后一步是均值不等式,忽略常数后当 k=n23 时取到,原式最小值即为 Θ(n23)。
给定正整数n,求:
ans1=n∑i=1φ(i)ans2=n∑i=1μ(i)
由μ⋅I=ϵ,很自然想到F=ϵ,g=I,代入原式子即得
S(n)=1−n∑d=2S(nd)
同时,因为φ⋅I=id,代入一般式得
S(n)=n⋅(n+1)2−n∑d=2S(nd)
类似地,我们使用整除分块+记忆化搜索解决。但是出杜教筛的题n一般较大,可以手写个 hash 或者直接使用unordered_map
解决。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现