狄利克雷前/后缀和

简介

考虑解决如下问题:

\[n = 1 \sim N, f(n) = \sum_{d \mid n} g(d), f^\prime(d) = \sum_{d \mid n} g(n) \]

这个问题就是狄利克雷前/后缀和,也就是求 \(f = g * 1,f^\prime * 1 = g\)

分析

朴素计算的复杂度是调和级数级别 \(\mathcal O(n \ln n)\),但我们希望得到近似线性的做法。

首先考虑狄利克雷求和累计的特点,对于一个 \(d\),设它能贡献到的集合为 \(S_d = \{n:d \mid n\}\),显然,若 \(d^\prime \mid d\),有 \(S_{d^\prime} \subset S_d\)

显然,这又大量重复的贡献,考虑着手优化。我们发现每个质因子是独立的,我们考虑将每一个质因子的次数设为一个维度,那么这件事就等价于求高维前缀和,复杂度 \(\mathcal O(n\log\log n)\)

for (int i = 1; i <= tot; i++)
    for (int j = 1; j * pr[i] <= n; j++)
        f[j * pr[i]] += f[j];

考虑高维后缀和类似,至于要倒过来做就行了:

for (int i = 1; i <= tot; i++)
    for (int j = n / pr[i]; j; j--)
        f[j] += f[j * pr[i]];

狄利克雷差分

其实相当于逆推狄利克雷前缀和,把两个循环都反过来枚举就行了:

for (int i = tot; i; i--)
    for (int j = n / pr[i]; j; j--)
        f[j * pr[i]] -= f[j];
for (int i = tot; i; i--)
    for (int j = 1; j * pr[i] <= n; j++)
        f[j] -= f[j * pr[i]];

例题

P8322 『JROI-4』少女幻葬

P8570 [JRKSJ R6] 牵连的世界

posted @ 2023-10-10 19:38  JWRuixi  阅读(60)  评论(0)    收藏  举报