从基础数论函数说起2:杜教筛

前置要求

从基础数论函数说起1:整除分块、数论函数、狄利克雷卷积

杜教筛

一部分数论题会问一个数论函数的前缀和,不妨令其为 (S(n)=sumlimits_{i=1}^n f(i)) 。有时直接求会比较困难。

杜教筛是通过构建一个函数 (g)(f*g) 的前缀和能快速( (O(1)) )求出。这样能在低于线性的复杂度内求解 (S(n))

具体地来说就是:

[egin{aligned} sumlimits_{k=1}^{n}sumlimits_{ij=k}f(i)g(j)=sumlimits_{ijleqslant n}f(i)g(j)=sumlimits_{i=1}^n g(i)S(lfloorfrac{n}{i} floor) end{aligned} ]

那么

[g(1)S(n)=sumlimits_{ijleqslant n}f(i)g(j)-sumlimits_{i=2}^ng(i)S(lfloorfrac{n}{i} floor) ]

好像还是没有讲清楚……

举个例子:

比方说 (f=mu)(S(n)=sumlimits_{i=1}^n f(i)) 。那么可以构造 (g=id_0) ,那么有

[g(1)S(n)=sumlimits_{i=1}^n (f*g)(i) - sumlimits_{i=2}^n g(1)S(lfloorfrac{n}{i} floor) ]

可以得到

[S(n)=1-sum_{i=2}^n S(lfloorfrac{n}{i} floor) ]

时间复杂度

计算 (S(n)) 的时候,需要知道 (S(frac{n}{i}),iin (2, n)) 。这个可以进行整除分块。也就是说,假设我们已经知道了 (S(1cdots n-1)) ,那么计算 (S(n)) 的复杂度是 (O(sqrt{n})) 的。

(S(n)) 分为两部分考虑。 当 (igeqslant sqrt{n}) 时, (frac{n}{i}leqslant n) 。那么假设把 (S(1cdotssqrt{n})) 全算了,时间复杂度是 (O(sumlimits_{i=1}^{sqrt{n}} sqrt{i})) 的。

再考虑 (ileqslant sqrt{n}) 的情况。由于 (lfloorfrac{lfloorfrac{n}{i} floor}{j} floor=lfloorfrac{n}{ij} floor) ,那么下标大于 (sqrt{n})(S) 在递归过程中 总共 只会被访问到 (O(sqrt{n})) 个。那么求出这 (O(sqrt{n})) 个的时间复杂度是 (O(sumlimits_{i=1}^{sqrt{n}} sqrt{frac{n}{i}}))

后一部分的复杂度显然大于前一部分。所以总的时间复杂度是

[O(sumlimits_{i=1}^{sqrt{n}} sqrt{frac{n}{i}})approx O(int_{0}^{sqrt{n}}sqrt{frac{n}{x}}dx)=O(n^{frac{3}{4}}) ]

而实际上可以做得更好。前面计算第一部分的时候,假设了计算了所有的 (S(1cdotssqrt{n})) 。但最后计算的时候,仍然是舍去的。不妨考虑稍微多预处理一点,来换取总的较小的复杂度。

根据前人经验,用线性筛预处理前 (n^{frac{2}{3}}) 项。那么预处理的时间复杂度是 (O(n^{frac{2}{3}})) 。然后后面一部分的复杂度就变为了

[O(sumlimits_{i=1}^{n^{frac{1}{3}}} frac{n}{i})approx O(int_{i=0}^{n^{frac{1}{3}}} sqrt{frac{n}{x}} dx) = O(n^{frac{2}{3}}) ]

优化常数和空间

由于上面提到的, (lfloorfrac{lfloorfrac{n}{i} floor}{j} floor=lfloorfrac{n}{ij} floor) ,需要求出的 (S) 的下标都是 (n) 的约数。所以可以将下标大于 (sqrt{n})(S) 存在另一个数组的 (frac{n}{i}) 里。这样就省去了 hash 或者 map 。

原文地址:https://www.cnblogs.com/chy-2003/p/11832146.html