一些常见筛法,还有一点新东西。
数论函数可以看做多元的形式幂级数,用 xiei 的系数表示 F(∏i=1npiei),比如 e=[n=1] 表示为 1,常值函数 1 表示为 ∏(1+xi+xi2+xi3+⋯),莫比乌斯函数 μ 表示为 ∏(1−xi)。
积性函数的特点是形式幂级数可以表示为若干个一元形式幂级数的乘积,形如 ∏Fi(xi),而完全积性函数满足 Fi(x)=1−aix1。
两个函数的狄利克雷卷积可以表示为两个形式幂级数相乘,特别地,积性函数只需要把每个一元形式幂级数对应相乘即可。同时狄利克雷卷积的逆运算(下面称做狄利克雷除法)可以表示为两个形式幂级数相除,因此两个积性函数相除也是积性函数。
设 D(n) 表示 {⌊in⌋∣1≤i≤n}。
积性函数前缀和有关问题主要分为两类:都是给定积性函数 F,设 sumF(n)=∑i=1nF(i),一类是求 sumF(n),另一类需要对所有 x∈D(n),求出 sumF(x)。
杜教筛
算法描述
杜教筛可以对满足一定性质的积性函数 F 在所有 D(n) 处求前缀和,复杂度为 O(n32)。
找到函数 G,设 H=F⋅G,这里是狄利克雷卷积,满足 G 和 H 的前缀和都很好算。那么
sumH(n)=i⋅j≤n∑F(i)G(j)=j=1∑nG(j)⋅sumF(⌊jn⌋)=i∈D(n)∑sumF(i)⋅(sumG(⌊in⌋)−sumG(⌊i+1n⌋)
把 sumF(n) 提到左边:
sumF(n)=sumH(n)−i∈D(n)∖{n}∑sumF(i)⋅(sumG(⌊in⌋)−sumG(⌊i+1n⌋)
按照上式对 D(n) 中的元素 x 从小到大去计算上式,单次复杂度为 O(x),总复杂度表示为
i=1∑ni+i=1∑nin≈i=1∑nin≈∫0nxndx=n43
注意到积性函数可以用线性筛来求较小的前缀和,如果对前 n32 线性筛,那么只需要对 D(n) 中大于 n32 的元素跑整除分块,复杂度降为 O(n32)。
扩展
杜教筛是利用 G 和 H 在 D(n) 处的前缀和计算出 H/G 在 D(n) 处的前缀和,这说明数论函数在 D(n) 处的前缀和在卷积和除法下具有封闭性。
形式化的,设 SF(n) 表示 {sumF(x)∣x∈D(n)}。给定 SF(n) 和 SG(n),可以求出 SF⋅G(n) 和 SF/G(n),其中 SF/G(n) 就是杜教筛,SF⋅G(n) 类似于杜教筛。因此 SF(n) 构成一个四则运算封闭的域。
计算 SF⋅G(n) 的朴素的实现是 O(n43) 的,但可以优化,下面给出一个引理:
设 SF(n) 的差分函数
diff(SF(n))={sumF(i)−sumF(⌊⌊n/i⌋+1n⌋)0(i∈D(n))(otherwise)
那么 F⋅G 和 diff(SF(n))⋅diff(SG(n)) 在 D(n) 处的前缀和相等。
把 SF⋅G(n) 分成 [1,log2nn),[log2nn,n] 两部分,前一部分使用差分加狄利克雷卷积,后一部分整除分块,复杂度 O(n32log31n)。
特别地,如果 F 和 G 都是积性函数,那么可以做到 O(n32)。如果知道 F 和 G 的定义可以直接线性筛,否则需要更复杂的做法,不过既然知道是积性函数一般也知道定义。
应用
求 sumμ(n) 和 sumφ(n)
μ=1e,φ=1id,直接杜教筛。另外 Sμ(n) 和 Sφ(n) 也可以相互转化。
给定多项式 A,B,求 ∑i=1nμ(i)A(i)B(⌊in⌋)。
对每个 k 分别求出 μ(i)ik 在 D(n) 处的前缀和,再枚举 ⌊in⌋ 统计答案。
其中 μ(i)ik 的狄利克雷卷积逆元是 F(i)=ik,F(i) 的前缀和可以快速求。
除数函数 σk(n) 表示 n 所有因数的 k 次方之和,对 x∈D(n) 求出 sumσk(n)。
函数 F(i)=ik 与 1 的狄利克雷卷积,扩展中介绍的方法。
有一个变量 x 初始为 1,每次随机一个整数 k∈[2,m],然后令 x=x⋅k,求 x>n 的期望步数。
设 F(i) 表示到达 x=i 这个状态的概率,那么答案为 sumF(n)。
设 G(i)={m−110(i∈[2,m])(otherwise),那么 F=e+G+G2+G3+⋯=e−G1。
因为 e−G 的前缀和是好求的,但 F 并不是积性函数,所以只能用 O(n32log31n) 的算法。
杜教筛并不要求函数是积性的,只要能通过简单函数四则运算得到就可以求。
对于满足 F(1)=1 的数论函数 F,定义 F 为一个函数 G 满足 G⋅G=F,且 G(1)=1,可以说明 G 是唯一的,给定 F 在 D(n) 处的前缀和 SF(n),求 SG(n)。
设 H=G−e,那么 H2+2H+e=F⇒H=21(F−e)−21H2。
可以发现 H 是自己卷自己的形式,扩展中介绍的算法是在线的,因此 SH(n) 可以从小大逐项计算,复杂度 O(n32log31n)。
杜教筛还可以解数论函数的代数方程。
Powerful Number 筛
算法描述
Powerful Number 筛可以对满足一定性质的积性函数 F 算一次前缀和,复杂度为 O(n)。
Powerful Number 定义:所有质因子的指数都大于 1 的数叫 Powerful Number。
引理:n 以内的 Powerful Number 的数量为 O(n) 级别。
证明:Powerful Number 可以表示为 a2b3,枚举 a,可以算出数量的上界:
i=1∑n3a2n<∫0n3a2nda=3n
找到一个积性函数 G 满足 G(x)=F(x)(x∈Prime),设 H=F/G,即狄利克雷除法,可知 H(x) 仅在 Powerful Number 和 1 处取值不为 0(形式幂级数上一次项都为 0)。
首先预处理出 H(x) 在 pk(p∈Prime,k>1) 处的取值,这里可以做到 O(N)(无论 O(1) 算 H(pk) 还是 O(k) 算都是这个复杂度)。然后通过 dfs 各个质因子的指数可以遍历 Powerful Number,同时也可以算出它们在 H 上的取值。
于是
sumF(i)=ab≤n∑G(a)H(b)=b=1∑nH(b)sumG(⌊bn⌋)
最后要求 G 的前缀和好求或者在 D(n) 处的前缀和能快速求。
扩展
称一个只在 Powerful Number 和 1 处取值不为 0 积性函数 H 为稀疏函数。
上述筛法是把 F 拆成 G 和一个稀疏函数 H 的狄利克雷卷积,然后考虑 H 中非 0 项对答案的贡献。
稀疏函数 H 有一个性质是 SH(n) 由 O(3n) 个值相等的连续段构成,证明考虑把 D(n) 拆成两段 [1,n32),[n32,n],前一段中只有 O(3n) 个 Powerful Number,因此前缀和只有 O(3n) 种,后一段中只有 O(3n) 个元素。
通过这个性质,对 Powerful Number 排序并处理前缀和,可以 O(3n)(可能要带 log)查询 sumF(n),从而降低多测的复杂度。
另外,可以以低于杜教筛的复杂度求出 F 在所有 D(n) 处的前缀和,对前 n53 线性筛,>n53 的部分用立方根整除分块即可做到 O(n53) 的总复杂度。
进一步,对于积性函数 F 和稀疏函数 G,给定 SF(n) 和 SG(n),可以 O(n53) 的复杂度计算 SF⋅G(n) 和 SF/G(n),由于 O(n53) 比任何通用筛法复杂度要低,因此积性函数的前缀和和完全积性函数的前缀和应该是等难的。
应用
定义函数 F(x) 表示最大的 b 使得 x=ab2,求 sumF(n)(n≤1015),2000 组询问。
F 在质数处的取值为 1,所以 F 可以表示 1 和一个稀疏函数的狄利克雷卷积,特别地,这个稀疏函数只在完全平方数处有值,每次询问使用立方根整除分块。
定义积性函数 F(x) 满足 F(pc)=p⊕c,求 F 在所有 D(n) 处的前缀和。
注意到 F 和 φ 在奇质数处的取值相同,但 2 处不同,令 F=φ⋅G,G 只在 Powerful Number 和 2k 的乘积还有 1 处取值非 0,这个数量是 O(n+2n+4n+⋯)=O(n),所以仍然可以将 G 视作稀疏函数,先用杜教筛求出 Sφ(n),然后可以 O(n53) 乘上 SG(n)。
扩展埃氏筛(min_25 筛,洲阁筛)
算法描述
这两种筛法可以对 pc 处定义简单的的积性函数求前缀和,min_25 筛复杂度为 O(n1−ϵ) 但可以跑 1012,洲阁筛为 O(n43⋅log−1n),并且洲阁筛可以计算出在所有 D(n) 处的前缀和。
两种筛法的第一部分都是求出 F 在质数处的取值。
首先找若干个完全积性函数 Hi 使得 F(x)=∑kiHi(x)(x∈Prime),对每个完全积性函数 Hi 分别算出在质数处的取值,现在考虑只有一个 H 的情况。
考虑埃氏筛,从小到大枚举每一个质数,把以这个质数为最小质因子的合数筛掉。
pi 表示第 i 个质数,di 表示 i 的最小质因子。
设 g(n,i)=∑j=2n[j∈P∨dj>pi]H(j),转移为
g(n,i)=g(n,i−1)−H(pi)(g(⌊pin⌋,i−1)−j=1∑i−1H(pj))
减后面那项是因为 pipj(j<i) 的最小质因子不是 pi。
当 n<pi2 时,g(n,i)=g(n,i−1),即不需要转移,这是复杂度的关键。
初始化 g(n,0)=i=2∑nH(i),注意 1 不算。
复杂度为 O(n43⋅log−1n),分析较为复杂。
min_25 筛的第二部分为一个复杂度为 O(n1−ϵ) 的搜索,从小到大枚举每个质因子的指数,如果后面只剩一个质因子且指数为 1,那么就使用前面计算的 g 数组,只递归考虑剩下质因子的指数和大于 1 的情况。
S(n,i)==j=2∑n[dj>pi]f(j)j=i+1∑pj≤nf(pj)+j=i+1∑pj2≤nk=1∑pjk≤nf(pjk)(S(⌊pjkn⌋,j)+[k>1])
答案是 S(N,0)+1。
洲阁筛的第二部分复杂度是 O(n43⋅log−1n),它相当于第一部分的逆过程,倒着把第一部分筛掉的合数加回去,但由于 F 不是完全积性函数,要复杂一点。
设 g(n,i)=∑j=2n[j∈P∨dj>pi]F(j),转移为
g(n,i−1)=g(n,i)+k≥1∑F(pik)(g(⌊pikn⌋,i−1)−j=1∑i−1F(pj))
和第一部分相比有几倍的常数,但复杂度不变。另外,Powerful Number 筛可以把积性函数的问题转化为完全积性函数的问题,提高这部分的速度。
扩展
另外,洲阁筛计算得到的信息天然就是按最小质因子分类的,而 min_25 筛在搜索中也容易记录最小质因子。
应用
求 [1,n] 中的质数个数。
相当于求 1 函数在质数处的取值之和,对应两种筛法的第一部分,复杂度 O(n43⋅log−1n)。
定义积性函数 F(x) 满足 F(pc)=p⊕c,求 F 在所有 D(n) 处的前缀和。
F(p)=p−1+2[n=2],先计算质数数量和质数和,再加上 n=2 的贡献就可以得到 F 在质数处的取值,然后再使用洲阁筛的第二部分,min_25 筛不太行。
继续考虑上面的积性函数 F,再给定多项式 A,求 ∑i=1nF(i)B(di),其中 di 表示 i 的最小质因子。
考虑分开计算质数和合数的贡献,质数的贡献就是 F(i)B(i) 在质数处的取值和,可以用第一部分计算。对于合数,我们把它们按最小质因子分类,对每一类算出 F 函数之和,这可以在洲阁筛第二部分过程中统计,再乘上 B(di)。
比较
-
三种筛法通过改进都可以解决积性函数在所有 D(n) 处的前缀和。
-
速度从高到低依次为:Powerful Number 筛,扩展埃氏筛,杜教筛。
-
在实现难度上,Powerful Number 筛和杜教筛比较容易,两种扩展埃氏筛要麻烦一点。
-
在多次询问时,Powerful Number 筛可以优化到 O(3n),杜教筛可以通过调整阈值来提高速度,扩展埃氏筛不行。
-
在适用范围上,扩展埃氏筛在积性函数上通用,应该是完全覆盖 Powerful Number 筛的,杜教筛可以计算一些非积性函数的前缀和。
对于一个积性函数求和问题,个人认为应该首选原生的 Powerful Number 筛,再考虑杜教筛,最后考虑两种扩展埃氏筛。
参考资料