Dirichlet 前缀和的几种版本

Posted yijan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dirichlet 前缀和的几种版本相关的知识,希望对你有一定的参考价值。

【模板】Dirichlet 前缀和


[ B[i] = sum_{d|i} A[d] ]
$ n le 2 imes 10^{7} $

看代码:

for( int i = 1 ; i <= en && pri[i] <= n ; ++ i ) {
        for (int j = 1; j * pri[i] <= n; ++j) {
            B[j * pri[i]] += B[j];
        }
    }

为啥这么做它是对的呢?发现每个数字会被它除以所有质因子转移到,并且是按照质因子从小到大来的。

所以这个代码相当于,对所有质因子递归求,然后对对所有质因子搞前缀和。

形式和 埃筛 一样,复杂度也是 $ O(nloglog n) $

然后考虑这个
[ B[i] = sum_{i|d} A[d] ]
看代码:

for( int i = 1 ; i <= en && pri[i] <= n ; ++ i ) {
        for (int j = n / pri[i]; j; --j) {
            B[j] += B[j * pri[i]];
        }
    }

首先,我们发现最主要的区别在于,我们应当从 一个数字本身 转移到 这个数字除以所有质因子。因为是从大到小转移的,所以也需要逆序枚举 $ j $ 。

最后考虑这个:
[ A[i] = sum_{d|i} B[d] ]
也是已知 $ A $ 求 $ B $

这种情况其实就是第一种情况反过来,我们也可以直接把循环顺序和转移方法给反过来

for( int i = en ; i ; -- i ) {
        for (int j = n / pri[i]; j ; -- j) {
            B[j * pri[i]] -= B[j];
        }
    }

第二种情况也可以反过来,就不赘述了。

例题:CF585E

以上是关于Dirichlet 前缀和的几种版本的主要内容,如果未能解决你的问题,请参考以下文章

关于求最大子段和的几种算法

康复计划#3 简单常用的几种计算自然数幂和的方法

一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式

一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式

一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式

一张图帮你记忆,Spring Boot 应用在启动阶段执行代码的几种方式