一种求特殊积性函数前缀和的筛法——Extended Eratosthenes Sieve

序:

关于这个筛法,此前是在学习了杜教筛的基础上的,杜教筛有良好的复杂度 O ( n 2 3 ) O(n^\frac{2}{3}) O(n32),而且实现简单。唯一的不足之处就是函数本身需要满足一些特殊的条件(即我们需要找另一个积性函数,使其与所求函数的狄利克雷卷积是一个很容易求前缀的式子),而且与函数本身的积性性质没有太大关系。后来接触到洲阁筛,这种筛法是一种解决更加广泛的积性函数前缀和,但是实在不太好写(因为我太菜了),后来在秦皇岛,复旦的温老师介绍了一个新的筛法,不过后来老师没怎么讲这个,因为时间不够了,然后就很匆忙提了一下。对于这么偏的东西,我还是去刷其他的题去了。。。后来一次偶然的机会,我遇到了一个类似的需要用这种方法的题目,后来就决定自己学EES,网上一查,发现根本就没有这样的东西。。。后来按照课件,我大概是明白了一点,但是还有后半部的问题,我始终没有解决,而且这个东西我周围没一个人会,网上也查不到。。。于是这篇写了一半草稿在18年9月就一直封存着了,后来就慢慢忘了。。。直到前几天,偶然的机会,又谈到这个问题,终于搞明白了。

提出问题:
f ( x ) 是 一 个 积 性 函 数 , 且 当 x = p k 时 ( p 为 质 数 ) , f ( x ) 是 一 个 关 于 p 的 多 项 式 f(x)是一个积性函数,且当x=p^k时(p为质数),f(x)是一个关于p的多项式 f(x)x=pk(p)f(x)p
S ( n ) = ∑ i = 1 n f ( i ) , n &lt; = 1 0 12 S(n)=\sum_{i=1}^nf(i),n&lt;=10^{12} S(n)=i=1nf(i),n<=1012
问题的一般化描述便是如此。显然问题的难点是在n的数量级上。这种筛法便是解决相关问题,如果n小于 1 0 8 10^{8} 108,我们可以用欧拉线性筛在 O ( n ) O(n) O(n)的时间复杂度解决这个问题。

分析:

设自然数集合 N = { x ∣ 2 &lt; = x &lt; = n } N=\{ x|2&lt;=x&lt;=n\} N={x2<=x<=n},我们按照一种划分标准,将这个集合里的数分成两部分。
这个标准是,先把一个数 x x x唯一分解: x = ∏ i = 1 k p i a i , p i 为 质 数 , p i &lt; p i + 1 , a i &gt; = 1 x=\prod_{i=1}^k p_i^{a_i},p_i为质数,p_i&lt;p_{i+1},a_i&gt;=1 x=i=1kpiai,pipi<pi+1,ai>=1
划分标准为:我们取这个数的最大质因子 p k p_k pk,若这个质因子的次数即 a k = 1 a_k=1 ak=1,即x属于集合 N 1 N_1 N1,反之,x属于 N 2 N_2 N2,即 a k &gt; 1 a_k&gt;1 ak>1
显然 N 1 ∩ N 2 = ∅ , N 1 ∪ N 2 = N N_1\cap N_2=\emptyset,N_1\cup N_2=N N1N2=,N1N2=N

N 1 , N 2 N_1,N_2 N1,N2中的数,我们来讨论一下他们的性质,很容易证明有: ∀ x ∈ N 1 , 则 ( 若 存 在 ) 其 次 大 质 因 子 p k − 1 &lt; n \forall x \in N_1,则(若存在)其次大质因子p_{k-1}&lt;\sqrt n xN1,()pk1<n

∀ x ∈ N 2 , 则 其 最 大 质 因 子 p k &lt; = n \forall x \in N_2,则其最大质因子p_{k}&lt;=\sqrt n xN2,pk<=n
解决问题的第一步:

现在我们枚举一类数 x x x,我们记 P x P^x Px x x x的质因子的集合,

我们枚举集合 N N N中的数x,满足: ∀ p ∈ P x , p &lt; = n \forall p\in P^x,p&lt;=\sqrt n pPx,p<=n

满则条件的x构成一个集合,记为 N 1 2 N^{\frac{1}{2}} N21,

那么实现的时候,我们可以DFS n \sqrt n n 以内的质因子.当 n &lt; 1 0 13 n&lt;10^{13} n<1013时, ∣ N 1 2 ∣ ≈ n 3 4 l o g n |N^{\frac{1}{2}}|\approx \frac{n^{\frac{3}{4}}}{logn} N21lognn43,这里的证明比较复杂,暂不讨论。

接下来,我们记 L x 为 x L_x为x Lxx的最大质因子。

对于答案来说这个集合里的还少了质因子是大于 n \sqrt n n 的数

现在我们枚举来集合 N 1 2 N^{\frac{1}{2}} N21,
∀ x ∈ N 1 2 如 果   x ∈ N 1 , 则 S ( n ) + = f ( x ) ∗ ∑ L x &lt; i &lt; = n x [ i 是 质 数 ] ∗ f ( i ) 反 之 , S ( n ) + = f ( x ) \forall x \in N^{\frac{1}{2}}\\ 如果\ x\in N_1,则S(n)+=f(x)*\sum_{L_x&lt;i&lt;=\frac{n}{x}}[i是质数]*f(i)\\反之,S(n)+=f(x) xN21 xN1,S(n)+=f(x)Lx<i<=xn[i]f(i)S(n)+=f(x)

显然,这里是利用了函数的积性来求得那些质因子是大于 n \sqrt n n 的数对于答案的贡献。
在实现的时候,显然当 L x &gt; = n x L_x&gt;=\frac{n}{x} Lx>=xn,可以及时退出,不然对效率还是有影响的。

问题转化为一个子问题:

那么现在的问题就只剩下求 ∑ L x &lt; i &lt; = n x [ i 是 质 数 ] ∗ f ( i ) \sum_{L_x&lt;i&lt;=\frac{n}{x}}[i是质数]*f(i) Lx<i<=xn[i]f(i)
我们记: g ( n ) = ∑ i = 1 n [ i 是 质 数 ] ∗ f ( i ) g(n)=\sum_{i=1}^n[i是质数]*f(i) g(n)=i=1n[i]f(i),
则求的是 g ( ⌊ n x ⌋ ) − g ( L x ) g(\lfloor\frac{n}{x}\rfloor)-g(L_x) g(xn)g(Lx)

因为 L x L_x Lx是小于 n \sqrt n n ,所以这里欧拉筛也可以处理,反正这个很容易处理。

现在问题的真正关键是求 g ( ⌊ n x ⌋ ) ( 或 g ( n ) ) g(\lfloor\frac{n}{x}\rfloor)(或g(n)) g(xn)(g(n)),

回过头观察 f ( x ) f(x) f(x), f ( x ) f(x) f(x)是只有在x为质数是才有多项式,我们不妨设一个函数 f ′ ( x ) f&#x27;(x) f(x),他对于全体整数都满足这个多项式,那么我们发现: g ( n ) = ∑ i = 1 n [ i 是 质 数 ] ∗ f ( i ) = ∑ i = 1 n [ i 是 质 数 ] ∗ f ′ ( i ) g(n)=\sum_{i=1}^n[i是质数]*f(i)=\sum_{i=1}^n[i是质数]*f&#x27;(i) g(n)=i=1n[i]f(i)=i=1n[i]f(i),

而多向式的求和,是很容易的!我们只要把不符合条件的筛掉就可以,并且显然 f ′ ( x ) f&#x27;(x) f(x)是完全积性函数,即 f ′ ( a b ) = f ′ ( a ) f ′ ( b ) f&#x27;(ab)=f&#x27;(a)f&#x27;(b) f(ab)=f(a)f(b)

假设这个多项式有k次: ∑ i k a i p i \sum_i^{k}a_ip^i ikaipi,那么实际上我们只要执行下面的算法k+1次, a i a_i ai这个系数在执行完以后在乘上就行,所以我们只要先讨论: f ′ ( p ) = p k f&#x27;(p)=p^k f(p)=pk,这个东西求和不难,组合数学的东西

解决子问题:

我们可以回想一下 E r a t o s t h e n e s   S i e v e Eratosthenes\ Sieve Eratosthenes Sieve的筛法是怎么样的。从小到大,枚举质数把后面的是这个是质数倍数的数去除。实际上这个也是这样的: 从 小 到 大 枚 举 p ∈ P , 且 p &lt; = n 从小到大枚举p \in P,且p&lt;=\sqrt n pPp<=n
给定 p p p以后,我们枚举i: 从 大 到 小 枚 举 i ∈ N , 当 i &lt; p 2 停 止 枚 举 从大到小枚举i\in N,当i&lt;p^2停止枚举 iN,i<p2
利用 f ′ ( x ) f&#x27;(x) f(x)的完全积性,执行下面的操作: g [ i ] − = ( g [ ⌊ i p ⌋ ] − g [ p − 1 ] ) ∗ f ′ ( p ) g[i]-=(g[\lfloor\frac{i}{p}\rfloor]-g[p-1])*f&#x27;(p) g[i]=(g[pi]g[p1])f(p)
解释一下: g [ i ] g[i] g[i] g ( i ) g(i) g(i)含义略有不同, g [ i ] g[i] g[i]代表一个变量,存的是一个值, g ( i ) g(i) g(i)是一个精确的定义的函数,值不允许改变。
解释这个操作的意思,就是每次我们枚举 p p p以后的目的是,把所有的以 p p p为最小质因子的数,消除影响,就是减去他们的贡献, g ( p − 1 ) ∗ f ( p ) g(p-1)*f(p) g(p1)f(p)里面是所有的以 p p p为最大质因子的贡献,是减多了。在把他们加回来的操作。

需要注意一点的: g [ n ] g[n] g[n]在最初始的情况下,被填充的是 ∑ i = 2 n f ′ ( i ) = ∑ i = 2 n i k \sum_{i=2}^nf&#x27;(i)=\sum_{i=2}^ni^k i=2nf(i)=i=2nik.

回过头来看这个操作,假设我们枚举完了第 k k k个质数即 p k p_k pk,我们观察一下 g [ n ] g[n] g[n]里面的内容是什么,为方便起见,我们设为 g [ n ] k g[n]_k g[n]k g [ n ] k = ∑ i = 1 k f ( p i ) + ∑ p k &lt; x &lt; = n [ x 没 有 前 k 个 质 因 子 ] ∗ f ( x ) g[n]_k=\sum_{i=1}^kf(p_i)+\sum_{p_{k}&lt;x&lt;=n}[x没有前k个质因子]*f(x) g[n]k=i=1kf(pi)+pk<x<=n[xk]f(x)

P ′ = { p ∈ P , 且 p &lt; = n } P&#x27;=\{p \in P,且p&lt;=\sqrt n \} P={pPp<=n }

则: g [ n ] ∣ P ′ ∣ = ∑ i = 1 ∣ P ′ ∣ f ( p i ) + ∑ p k &lt; x &lt; = n [ x 没 有 前 ∣ P ′ ∣ 个 质 因 子 ] ∗ f ( x ) g[n]_{|P&#x27;|}=\sum_{i=1}^{|P&#x27;|}f(p_i)+\sum_{p_{k}&lt;x&lt;=n}[x没有前|P&#x27;|个质因子]*f(x) g[n]P=i=1Pf(pi)+pk<x<=n[xP]f(x)

显然,这里的 x x x都是质数,那么到这里: g [ n ] 等 于 g ( n ) g[n]等于g(n) g[n]g(n)

到这里真确性得以验证,到这里问题得到了理论上的解决。

关于复杂度:
温老师的ppt说每个可能用到的 g ( i ) g(i) g(i),只会在遍历不超过 n \sqrt n n 的质数访问到,因此,每个i贡献的时间复杂为 O ( i l o g i ) = O ( i l o g   i ) O(\frac{\sqrt i}{log \sqrt i})=O(\frac{\sqrt i}{log\ i}) O(logi i )=O(log ii )
总时间复杂度为: O ( ∑ i = 1 n i l o g   i + ∑ i = 1 n n i l o g   n i ) ≈ O ( n 3 4 l o g   n ) O(\sum_{i=1}^{\sqrt n}\frac{i}{log\ i}+\sum_{i=1}^{\sqrt n}\frac{\sqrt \frac{n}{i}}{log\ \sqrt \frac{n}{i}})\approx O(\frac{n^{\frac{3}{4}}}{log\ n}) O(i=1n log ii+i=1n log in in )O(log nn43)

举个例子:

比如求 g ( 12 ) g(12) g(12),只要枚举2,3两个因子就可以了,

初始 g [ 12 ] = ∑ i = 2 12 f ( 12 ) g[12]=\sum_{i=2}^{12}f(12) g[12]=i=212f(12),( g [ 1 ] = 0 g[1]=0 g[1]=0,显然)
枚举 2 2 2,则 g [ 12 ] − = ( g [ 6 ] − g [ 1 ] ) ∗ f ′ ( 2 ) g[12]-=(g[6]-g[1])*f&#x27;(2) g[12]=(g[6]g[1])f(2)
那么: g [ 12 ] = f ′ ( 2 ) + f ′ ( 3 ) + f ′ ( 4 ) + f ′ ( 5 ) + f ′ ( 6 ) + f ′ ( 7 ) + f ′ ( 8 ) + f ′ ( 9 ) + f ′ ( 10 ) + f ′ ( 11 ) + f ′ ( 12 ) g[12]=f&#x27;(2)+f&#x27;(3)+\sout{f&#x27;(4)}+f&#x27;(5)+\sout{f&#x27;(6)}+f&#x27;(7)+\sout{f&#x27;(8)}+f&#x27;(9)+\sout{f&#x27;(10)}+f&#x27;(11)+\sout{f&#x27;(12)} g[12]=f(2)+f(3)+f(4)+f(5)+f(6)+f(7)+f(8)+f(9)+f(10)+f(11)+f(12)枚举 3 3 3,则 g [ 12 ] − = ( g [ 4 ] − g [ 2 ] ) ∗ f ′ ( 3 ) g[12]-=(g[4]-g[2])*f&#x27;(3) g[12]=(g[4]g[2])f(3),这时 g [ 4 ] = f ′ ( 2 ) + f ′ ( 3 ) g[4]=f&#x27;(2)+f&#x27;(3) g[4]=f(2)+f(3),乘上 f ′ ( 3 ) f&#x27;(3) f(3)以后,相当于把 f ′ ( 6 ) f&#x27;(6) f(6)给多减了,因为枚举2时已经把 f ′ ( 6 ) f&#x27;(6) f(6)减了,所以这里 g [ 2 ] = f ′ ( 2 ) g[2]=f&#x27;(2) g[2]=f(2),乘上 f ′ ( 3 ) f&#x27;(3) f(3),又把 f ′ ( 6 ) f&#x27;(6) f(6)加回来。
那么: g [ 12 ] = f ′ ( 2 ) + f ′ ( 3 ) + f ′ ( 4 ) + f ′ ( 5 ) + f ′ ( 6 ) + f ′ ( 7 ) + f ′ ( 8 ) + f ′ ( 9 ) + f ′ ( 10 ) + f ′ ( 11 ) + f ′ ( 12 ) g[12]=f&#x27;(2)+f&#x27;(3)+\sout{f&#x27;(4)}+f&#x27;(5)+\sout{f&#x27;(6)}+f&#x27;(7)+\sout{f&#x27;(8)}+\sout{f&#x27;(9)}+\sout{f&#x27;(10)}+f&#x27;(11)+\sout{f&#x27;(12)} g[12]=f(2)+f(3)+f(4)+f(5)+f(6)+f(7)+f(8)+f(9)+f(10)+f(11)+f(12)
循环结束。

如有错误欢迎指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值