浅谈一类积性函数的前缀和

写在前面

笔者在刷题过程中遇到一些求积性函数前缀和的问题,当中有一类问题须要在低于线性时间复杂度的算法,今天就来浅析一下这类问题的求解方法。当作以后讲课使用的讲义。若之后有了新的研究,再来继续完好这篇文章。
本文会随时更新内容。建议以链接形式转载,或者与笔者保持联系。

爬虫转载不标明出处必究。

author: skywalkert
original article: http://blog.csdn.net/skywalkert/article/details/50500009
last update time : 2017-04-01


前置技能

积性函数的定义

  1. f(n)的定义域为正整数域,值域为复数。即f:Z+C,则称f(n)数论函数

  2. f(n)为数论函数。且f(1)=1,对于互质的正整数p,qf(pq)=f(p)f(q),则称其为积性函数
  3. f(n)为积性函数,且对于随意正整数p,q都有f(pq)=f(p)f(q)。则称其为全然积性函数

积性函数的性质与样例

  1. 常见的积性函数有
    • 除数函数σk(n)=d|ndk,表示n的约数的k次幂和,注意σk(n)σk(n)是不同的。
    • 约数个数函数τ(n)=σ0(n)=d|n1,表示n的约数个数,一般也写为d(n)

    • 约数和函数σ(n)=σ1(n)=d|nd,表示n的约数之和。
    • 欧拉函数φ(n)=ni=1[(n,i)=1]1,表示不大于n且与n互质的正整数个数,另外ni=1[(n,i)=1]i=nφ(n)+[n=1]2,且对于正整数n>2来说φ(n)是偶数。
    • 莫比乌斯函数μ(n),在狄利克雷卷积的乘法中与恒等函数互为逆元。μ(1)=1,对于无平方因子数n=ti=1piμ(n)=(1)t,对于有平方因子数nμ(n)=0
    • 元函数e(n)=[n=1],狄利克雷卷积的乘法单位元,全然积性。

    • 恒等函数I(n)=1,全然积性。
    • 单位函数id(n)=n。全然积性。

    • 幂函数idk(n)=nk,全然积性。
  2. 关于莫比乌斯函数和欧拉函数有两个经典的公式
    • [n=1]=d|nμ(d)。将μ(d)看作是容斥的系数就可以证明。

    • n=d|nφ(d),将in(1in)化为最简分数统计个数就可以证明。
  3. f(n)为积性函数。则对于正整数n=ti=1pkiif(n)=ti=1f(pkii);若f(n)为全然积性函数,则对于正整数n=ti=1pkiif(n)=ti=1f(pi)ki

狄利克雷卷积与莫比乌斯反演

  1. 数论函数fg狄利克雷卷积定义为(fg)(n)=d|nf(d)g(nd),狄利克雷卷积满足交换律、结合律。对加法满足分配律,存在单位元函数e(n)=[n=1]使得fe=f=ef,若fg为积性函数则fg也为积性函数。
  2. 狄利克雷卷积的一个经常使用技巧是对于积性函数f与恒等函数I的卷积的处理,比如n=ti=1pkii,g(n)=d|nf(d),则有g(n)=ti=1kij=0f(pji)
  3. 莫比乌斯反演也是对于g(n)=d|nf(d)的讨论。可是不要求f是积性函数,适用于已知g(n)f(n)的情况,因为Iμ=e,则gμ=fIμ=fe=f,即f(n)=d|ng(d)μ(nd),相似地有g(n)=n|df(d)f(n)=n|dg(d)μ(dn),二项式反演也是相似的技巧。有一个样例能够看出欧拉函数和莫比乌斯函数之间的关系。因为d|nφ(d)=id(n)。所以φ(n)=d|nμ(d)nd,也即φ(n)n=d|nμ(d)d


正文:黑科技

这样的黑科技大概起源于Project Euler这个站点,由xudyh引入中国的OI、ACM界。眼下出现了一些OI模拟题、OJ月赛题、ACM赛题是须要这样的技巧在低于线性时间的复杂度下解决一类积性函数的前缀和问题。

首先看一个简单的样例。求前n个正整数的约数之和,即ni=1σ(i),当中n1012
显然不能直接做了。可是我们能够推导一番:

i=1nσ(i)=i=1nj=1n[j|i]j=i=1nij=1n[i|j]=i=1nini

in时,ni显然仅仅有O(n)个取值;当i>n时。ni<n显然也仅仅有O(n)个取值;对于固定的nii的取值是一段连续的区间,这段区间是[nni+1+1,nni]。因此能够O(n)计算所求。


相同地。求前n个正整数的约数个数之和也能够这样计算,留给读者练习。
另外须要说明的是,ni=1nii=ni=1ni(ni+1)2,这也是一种常见的表示形式。

如今我们来加大一点难度,求前n个正整数的欧拉函数之和,即ni=1φ(i),当中n1011


眼下本文提到的有关欧拉函数的公式仅仅有几个,能否用它们来帮助化简呢?答案是肯定的。接下来我们就利用d|nφ(d)=n来化简这个式子。
这个公式也能够看成是φ(n)=nd|n,d<nφ(d),设ϕ(n)=ni=1φ(i),则有

ϕ(n)=i=1nφ(i)=i=1nid|i,d<iφ(d)=n(n+1)2i=2nd|i,d<iφ(d)=n(n+1)2id=2nd=1nidφ(d)=n(n+1)2i=2nd=1niφ(d)=n(n+1)2i=2nϕ(ni)

那么仅仅要计算出O(n)ϕ(ni)的值。就能够计算出ϕ(n)。这样的复杂度又怎样呢?
如果计算出ϕ(n)的复杂度为T(n),则有T(n)=O(n)+ni=1T(i)+T(ni)这里仅仅展开一层就能够了,更深层的复杂度是高阶小量,所以有T(n)=ni=1O(i)+O(ni)=O(n34)
因为ϕ(n)是一个积性函数的前缀和,所以筛法也能够预处理一部分,如果预处理了前k个正整数的ϕ(n),且kn,则复杂度变为T(n)=nki=1ni=O(nk),当k=O(n23)时能够取到较好的复杂度T(n)=O(n23)
之前利用φ(n)=nd|n,d<nφ(d)的地方是怎么想到的呢?最好还是来看一下这个
n(n+1)2=i=1ni=i=1nd[d|i]φ(d)=id=1nd=1nidφ(d)=i=1nϕ(ni)

如果能通过狄利克雷卷积构造一个更好计算前缀和的函数。且用于卷积的还有一个函数也易计算,则能够简化计算过程。比如上题就是利用了φI=id的性质,但一定注意,不是全部的这一类题都仅仅用配个恒等函数I就能够轻松完事的。有时须要更仔细的观察。

定义梅滕斯函数M(n)=ni=1μ(i),给定正整数n,计算M(n),当中n1011
有了欧拉函数的经验,这次似乎就轻车熟路了吧,使用[n=1]=d|nμ(d)来试试?

1=i=1n[i=1]=i=1nd|iμ(d)=i=1nd=1niμ(d)=i=1nM(ni)

因此M(n)=1ni=2M(ni),问题可在O(n23)时间复杂度下解决。

看了上面的样例,是不是觉得这样的做法非常naive,非常好学啊。再来看一个题吧!
A(n)=ni=1i(n,i),F(n)=ni=1A(i)。求F(n)(109+7)的值。当中n109
先做一番化简,变成积性函数前缀和的样子:

A(n)=i=1ni(n,i)=i=1nd|n[(n,i)=d]id=d|nid=1nd[(nd,id)=1]id=12(1+d|ndφ(d))

G(n)=2F(n)n,则
G(n)=2F(n)n=i=1nd|idφ(d)=i=1nd=1nidφ(d)

因此要求的是ϕ(n)=ni=1iφ(i)


而对于n=ti=1pkii,有

d|ndφ(d)=i=1tj=0kipjiφ(pji)=i=1tp2ki+1i+1pi+1
这并非什么好算前缀和的函数。
可是不难发现(idφ)id=id2,即
d|ndφ(d)nd=nd|nφ(d)=n2
。这是一个非常好计算前缀和的函数,于是有
n(n+1)(2n+1)6=i=1ni2=i=1nd|idφ(d)id=id=1nidd=1niddφ(d)=i=1niϕ(ni)

因此ϕ(n)=n(n+1)(2n+1)6ni=2iϕ(ni),原问题可在预处理前O(n23)个值的基础上,在O(n23logn)的时间复杂度下解决。

可是注意到这样的方法的常数与复杂度都可能较高,有时候可能再进行一些推导能够得到一个不使用正文方法的做法,比如ZOJ 3881 - From the ABC conjecture,本文的方法与网上一个解法相似,能够用于求解此题。可是能够这样推导之后得到更简单的一个做法。

须要使用此种方法的题目一般数据规模较大,比如n109,n1011,n1012,可是并非都要使用此类方法。有时候可能存在其它O(n),O(n23)的做法,比如51Nod 1222 - 最小公倍数计数。会利用正文复杂度分析的方法就可以,再比如ZOJ 5340 - The Sum of Unitary Totient,笔者不是非常懂这题是否有其它做法能过,比如O(n34logn)的积性函数求和方法(会在不久后更新)。可能会因为数据组数较多而超时,网上的一个解法是分段压缩打表。详细问题须要详细分析。


推荐题目

这里给出一些练手的题目供大家理解上述方法,这类题还是较少的,如有其它题的题源欢迎分享。
51Nod 1244 - 莫比乌斯函数之和
51Nod 1239 - 欧拉函数之和
BZOJ 3944 - Sum
HDU 5608 - function
51Nod 1238 - 最小公倍数之和 V3
51Nod 1237 - 最大公约数之和 V3
51Nod 1227 - 平均最小公倍数
Tsinsen A1231 - Crash的数字表格
SPOJ DIVCNT2 - Counting Divisors (square)
51Nod 1222 - 最小公倍数计数(复杂度分析)
BZOJ 4176 - Lucas的数论
51Nod 1220 - 约数之和
51Nod 1584 - 加权约数和
ZOJ 3881 - From the ABC conjecture(不须要使用正文方法)
BZOJ 3512 - DZY Loves Math IV
ZOJ 5340 - The Sum of Unitary Totient常规积性函数求和,数据组数较多,仅仅可分段打表)
SPOJ DIVCNT3 - Counting Divisors (cube)常规积性函数求和,注意代码长度限制,不可打表)
51Nod 1575 - Gcd and Lcm常规积性函数求和。可分段打表)
51Nod 1847 - 奇怪的数学题(非常规积性函数求和,综合题,可分段打表)

Tips: 加粗内容为待更新内容。

posted on 2017-08-05 09:14  ljbguanli  阅读(442)  评论(0)    收藏  举报