狄利克雷相关
更新于 2026/7/5 10:46:12
作者
command_block
狄利克雷前缀和
首先需要掌握 位运算卷积(FWT)与其扩展 ,否则可能无法理解某些内容。
设 A+=A∗I ,即倍数求和, A−=A∗μ ,则倍数差分(逆运算)。
倍数求和直接枚举倍数暴力算即可,复杂度O(nlogn).
倍数差分可以莫比乌斯反演:
设容斥系数为g,有$A^-[n]=\sum\limits_{i=1}g(i)A[i]=\sum\limits_{i=1}g(i)\sum\limits_{i|j}A^-[j]$
提取A−[j]的贡献系数 : i∣j∑g(i)=[j=n],即能推出g(i)=[n∣i]μ(i/n)
回代可得A−[n]=n∣i∑μ(i/n)A[i],这同样可以枚举倍数达到O(nlogn).
我们在计算 and 卷积的时候,可以暴力枚举补集,但是复杂度为O(3n)不优。
类似地,我们在这里暴力枚举倍数也不够优。
这是前缀和而不是本文的倍数求和,不过原理类似。
考虑每个质因数是一维,做高维前缀和(其实就是卷 I ),代码是这样的:
for(int i=1;i<=tn;i++)
for(int j=1;j*p[i]<=n;j++)
F[j*p[i]]+=F[j];
类似地,有约数前缀差分(其实就是卷 μ )
for(int i=1;i<=tn;i++)
for(int j=n/p[i];j;j--)
F[j*p[i]]-=F[j];
以后想卷 I,μ 的时候,这样写会比暴力狄利克雷卷积快得多,还不用筛。
约数后缀和:
for(int i=1;i<=tn;i++)
for(int j=n/p[i];j;j--)
F[j]+=F[j*p[i]];
约数后缀差分:
for(int i=1;i<=tn;i++)
for(int j=1;j*p[i]<=n;j++)
F[j]-=F[j*p[i]];
根据埃氏筛法的复杂度分析,上述代码的复杂度均为 O(∑pnpn)=O(nloglogn)
形如 C[n]=(i,j)=n∑A[i]B[j] 的卷积,被称为 gcd 卷积。
我们可以先计算 C+[n]=n∣(i,j)∑A[i]B[j] ,然后再差分即可得到 C .
C+[n]=n∣(i,j)∑A[i]B[j]
=n∣i,n∣j∑A[i]B[j]
$=\big(\sum\limits_{n|i}A[i]\big)\big(\sum\limits_{n|j}B[j]\big)$
=A+[i]B+[j]
-
这从向量变换的角度容易理解:
gcd 的本质就是对每个质因子维度取 min.
类比 and 卷积,先要做高维后缀和,点乘再差分即可得到答案。
对应到 gcd 卷积上,即先要倍数求和,点乘再倍数差分。
-
快速狄利克雷卷积
可用于加速某些题目的预处理。
我们按照枚举倍数的传统方法计算狄利克雷卷积,复杂度是 O(nlogn) 的。
前面讲到过,对于卷 I,μ 的特殊情况,可以理解成在高维空间的前缀和/差分,从而使用高维变换优化。
实际上,对于任意的积性函数,也有类似的方法。
设 F 为积性函数, G 不是,欲求 F∗G 的前 n 项。
我们把 F 分解为若干个只和某个素数 p 有关的函数(变换) 的卷积,即 :
$F_p(n)=\begin{cases}F(n)&(n=p^k)\\0&{\rm otherwise}\end{cases}$
然后则有 F=p∈Prime∏Fp(n) ,这里的乘法是狄利克雷卷积。
简略证明 : 容易发现 Fp1∗Fp2 能够得到 n=p1k1p2k2 处的所有值,可以进一步推广到不交的质数集合卷积的情况。
也即 : 可以把一个积性函数拆成 π(n) 个只与单个质数有关的积性函数卷积。
我们把这些函数分别卷到 G 上去,就能得到答案。
考虑 (G∗Fp)(n)=d∣n∑G(n/d)Fp(d)
=pk∣n∑G(n/pk)Fp(pk)
考虑枚举每个 pk 的倍数计算该和式。(可以预先保存需要的 G)
考虑单个质数 p ,其贡献的复杂度为 O(k=1∑∞n/pk)
使用等比数列可算得其为 O(p−1n) 其实也与 O(pn) 同级。
所以复杂度仍然是 O(∑pnpn)=O(nloglogn)。
此外,对于每个 pk 都需要求出 F ,这样的 pk 的个数是 O(n/logn) 的。
对于 p≤n 的部分,贡献不超过 O(π(nlogn))=O(n) ,可不计。
对于 p>n 的部分,指数只能是 1 贡献不超过 O(π(n))=O(n/logn)。
所以,我们只需要为求解单个 F(pk) 找到一个 O(logn) 以内的复杂度即可。
狄利克雷生成函数
对于一个数论函数, F ,定义其狄利克雷生成函数为 :
F(s)=i=1∑isF[i]
由于 as∗bs 会贡献到 (ab)s ,两个数论函数的狄利克雷卷积就对应其 DGF 的卷积。
你可能会问为啥不用 is 而用 is1 ? 前者会导致级数不收敛……
本文中讨论的数论函数都是积性函数。
似乎没有贝尔级数好用,先咕了。
和生成函数没啥关系,只是数论函数求逆罢了。
F∗G=e
G[1]=1,d∣n∑F[n/d]G[d]=0
F[1]G[n]+d∣n,d=n∑F[n/d]G[d]=0
G[n]=−d∣n,d=n∑F[n/d]G[d]
复杂度 O(nlogn)。
当然还有更快的办法,先按照上文的方法将积性函数划分成若干个单素数积性函数,分别(多项式)求逆后,再卷积。
这样能做到 O(nloglogn)。
回忆 lnA=B⇒B=∫AA′ ,我们只需要再定义出导数和积分。
回忆指数函数的求导法则 (ax)′=axlna
但是此处 lna 无定义,一种广为流传的做法是,定义 lnn 为 n 的质因子幂次总和。
这样就能满足 lnab=lna+lnb 的关键性质。
积分只需要定义为逆运算即可。
要求 A[1]=0
回忆 $\exp A=B\Rightarrow \ln B=A\Rightarrow A'=\dfrac{B'}{B}\Rightarrow A'B=B'$
⇒d∣n∑B[d]A′[n/d]=B′[n]
A[1]B[n]+d∣n,d=n∑B[d]A′[n/d]=B′[n]
B′[n]=d∣n,d=n∑B[d]A′[n/d]
这就能 O(nlogn) 递推了。