芝士:积性函数的前缀和(杜教筛&min25)

问题

快速计算\(\sum_{i=1}^{n}f(i)\),其中保证\(f\)为一个积性函数,同时\(f(p)\)能用多项式表示,\(f(p^k)\)能够快速计算

杜教筛

杜教筛的范围比较广一点,只需要要求\(f\)是一个积性函数就可以了

这里有一种卷积形式,迪利克雷卷积

\(h(n)=\sum_{d|n}f(d)g(\frac{n}{d})\),简记为\(h(n)=(f*g)(n)\)

考虑构造一个\(g\),使得\(g\)也是一个积性函数,那么有\(h(n)=(f*g)(n)\)

因为\(g\)\(f\)均为积性函数,故\(h\)也为一个积性函数

\(H(n)=\sum_{i=1}^{n}h(i),F(n)=\sum_{i=1}^nf(i),G(n)=\sum_{i=1}^ng(i)\)

\[\begin{aligned} H(n)&=\sum_{i=1}^{n}h(i)\\ &=\sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d})\\ &=\sum_{i=1}^{n}\sum_{d|i}f(\frac{i}{d})g(d)\\ &=\sum_{d=1}^{n}g(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f(i)\\ &=\sum_{d=1}^{n}g(d)F(\lfloor\frac{n}{d}\rfloor)\\ &=g(1)F(n)+\sum_{d=2}^{n}g(d)F(\lfloor\frac{n}{d}\rfloor) \end{aligned} \]

\(F(n)=\frac{H(n)-\sum_{d=2}^{n}g(d)F(\lfloor\frac{n}{d}\rfloor)}{g(1)}\)

很显然,此时你需要快速计算\(H(n)\)\(G(d)\),所以这就是杜教筛的难点所在,即选择的\(g\)函数,和卷起来的\(h\)函数

杜教筛有两种打法,一种是直接暴力记忆化递归进行计算,其为\(O(n^\frac{3}{4})\)

一种是可以预处理出来\(n\)比较小的\(F(n)\),因为\(f(n)\)是一个积性函数,很容易就可以\(O(n)\)处理出一段,当预处理的\(N=n^{\frac{2}{3}}\)时,总的时间复杂度为\(O(n^{\frac{2}{3}})\)

同时其中有一些记忆化的步骤,可能要乘上记忆化的复杂度,这个就因人而异了

min25

如果面向这类对于积性函数前缀和的问题,相信杜教筛莫过于是一种很好的算法

但同时,如果找不到相应的积性函数\(g\)\(h\)就会比较难受,此时更加暴力一点的min25就有了用处

\(f\)是一个积性函数,那么可以尝试从质因数角度进行思考

\(\sum_{i=1}^{n}f(i)=f(1)+\sum_{i\in prime}^{n}f(i)+\sum_{i\notin prime,i\not= 1}^{n}f(i)\)

\(f'(i)\)\(f(i)\)\(i\)是质数时候的取值相同,但是\(f'(i)\)为完全积性函数

考虑一个奇奇怪怪的函数$g(n,m)=\sum_{i=1}^{n}f'(i)[i\in prime或者min(i)>pri_m] $

其中\(min(i)\)表示\(i\)的最小的一个质因数,\(pri_m\)表示第\(m\)大的质数

接下来考虑\(g(n,m)\)的转移,如果有\(pri_m^2>n\)的时候,也就是指此时合数至少都是\(pri_m^2\),但是这个是不计入贡献的,故有\(g(n,m)=g(n,m-1)\)

如果是\(pri_m^2\le n\)的时候,考虑\(g(n,m-1)\)\(g(n,m)\)之间的关系,

对两个条件分开来考虑,如果\(i\in prime\),那么两者都会统计进去,

如果\(i\notin prime\),那么此时差的是\(pri_m\)作为最小质因数所贡献的值,

因为\(f\)是一个积性函数,所以可以将其提出来

\(g(n,m)=g(n,m-1)-f'(pri_m)(g(\frac{n}{pri_m},m-1)-g(pri_{m-1},m-1))\)

所以就有\(g(n,m)=\begin{cases}g(n,m-1)\space pri_m^2>n\\g(n,m-1)-f'(pri_m)(g(\frac{n}{pri_m},m-1)-g(pri_{m-1},m-1))\space pri_m^2\le n\end{cases}\)

边界情况很显然就是\(m==0\)了,此时就必须暴力算出\(g(n,0)\)的值,当然,此处的\(n\)的大小是不保证的,所以要另外找方法算出其的值,这个因题目而异

那么很显然,如果手动地将\(m\)调地足够大,那么就可以求出来所有$i\in prime,f(i) \(的和,但是注意实际上求出来的是\)f'(i)\(的值,只不过两个函数在\)i\in prime$处取值相同而已

接着考虑合数的情况,设$s(n,m)=\sum_{i=1}^{n}f(i)[min(i)\ge pri_m] $

同样的,考虑递推,考虑每一个合数在\(min(i)>pri_m\)时候的贡献

\(s(n,m)=g(n,|prime|)-\sum_{i=1}^{m-1}f(pri_i)+\sum_{k=m}^{pri_k\le n}\sum_{e=1}^{pri_k^{e}\le n }s(\frac{n}{pri_k^e},k+1)f(pri_k^e)+f(p_k^{e+1})\)

那么就有$ans=\sum_{i=1}^nf(i)=f(1)+s(n,1) $,这里的质数集的大小就必须手动分析了

关于\(g\)\(h\)的复杂度,均为\(O(\frac{n^{\frac{3}{4}}}{log_n})\)

posted @ 2021-02-01 16:55  loney_s  阅读(355)  评论(0)    收藏  举报