杜教筛

杜教筛

前置:数论分块莫比乌斯反演狄利克雷卷积欧拉函数
对于数论函数 \(f(n)\),杜教筛能够在线性的时间复杂度内求得 \(\sum\limits_{i=1}^{n} f(i)\) 的值。
只要我们能够构造出另一个数论函数 \(g(n)\),使得 \(\sum\limits_{i=1}^{n}(f * g)(i)\) 能够以较快的时间复杂度求得,我们便能够使用杜教筛求得 \(\sum\limits_{i = 1}^{n} f(i)\) 的值。
我们设 \(S(n) = \sum\limits_{i = 1}^{n} f(i)\),我们则需要考虑构造出一个与 \(S(n)\) 有关的式子。

对于 \(\sum\limits_{i = 1}^{n} (f * g)(i)\),有,

\[\sum\limits_{i = 1}^{n} (f * g)(i) = \sum\limits_{i = 1}^{n} \sum\limits_{d | i} g(d) f(\frac{i}{d}) \]

注意此处我们将 \(\sum\limits_{i = 1}^{n} (f * g)(i)\) 使用狄利克雷卷积展开为 \(g(d) f(\frac{i}{d})\) 而非 \(f(d) g(\frac{i}{d})\) 的原因是为了构造出 \(S\)
枚举 \(d\),转换一下式子得,

\[\sum\limits_{d = 1}^{n} \sum\limits_{i = 1}^{\lfloor \frac{n}{d} \rfloor} g(d)f(i) \]

\(g(d)\) 提出来,

\[\sum\limits_{d = 1}^{n}g(d) \sum\limits_{i = 1}^{\lfloor \frac{n}{d} \rfloor} f(i) \]

根据 \(S(n)\) 的定义,后面这块式子可以变为 \(S(\lfloor \frac{n}{d} \rfloor)\)

\[\sum\limits_{d = 1}^{n}g(d) S(\lfloor \frac{n}{d} \rfloor) \]

为了构造 \(S(n)\),我们把 \(d = 1\) 时的式子拆开来

\[g(1)S(n) + \sum\limits_{i = 2}^{n}g(i) S(\lfloor \frac{n}{i} \rfloor) \]

移项可得:

\[g(1)S(n) = \sum\limits_{i = 1}^{n} (f * g)(i) - \sum\limits_{i = 2}^{n}g(i) S(\lfloor \frac{n}{i} \rfloor) \]

那么,对于 \(f(n)\),我们只要找到一个合适的数论函数 \(g(n)\) 便能够求解 \(S(n)\)

莫比乌斯函数

莫比乌斯函数,即 \(\mu(n)\)

我们令 \(g(n) = 1\)

\[\begin{aligned} S(n) &= \sum\limits_{i = 1}^{n} \sum\limits_{d | i} \mu(d) - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \\ &= \sum\limits_{i = 1}^{n} [n = 1] - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \\ &= 1 - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \\ \end{aligned} \]

至此,便可用数论分块求得。

$\text{Link}$
il int get_mu(int x) {
    if (x <= 10000000) return mu[x];
    if (res2[x]) return res2[x];
    int res = 1;
    for (ll l = 2,r; l <= x; l = r + 1 ) {
        r = x / (x / l);
        res -= (r - l + 1) * get_mu(x / l);
    }
    return res2[x] = res;
}

欧拉函数

欧拉函数,即 \(\varphi(n)\)

同样,令 \(g(n) = 1\)

\[\begin{aligned} S(n) &= \sum\limits_{i = 1}^{n} \sum\limits_{d | i} \varphi(d) - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \\ &= \sum\limits_{i = 1}^{n} i - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \\ &= \frac{(n + 1) \cdot n}{2} - \sum\limits_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor) \end{aligned} \]

至此,我们也能够使用数论分块解决。

$\text{Link}$
il ll get_phi(ll x) {
    if (x <= 10000000) return phi[x];
    if (res1[x]) return res1[x];
    ll res = 1ll * (1ll + x) * x / 2ll;
    for (ll l = 2,r; l <= x; l = r + 1 ) {
        r = x / (x / l);
        res -= 1ll * (r - l + 1ll) * get_phi(x / l);
    }
    return res1[x] = res;
}

时间复杂度

不会证明。

因为使用的数论分块递归,时间复杂度是 \(\mathcal{O(n^{\frac{3}{4}})}\)
但是如果我们提前预处理出前 \(n^{\frac{2}{3}}\) 的函数的值,则可以在 \(\mathcal{O(n^{\frac{2}{3}})}\) 的时间复杂度内解决。

posted @ 2024-03-01 14:08  songszh  阅读(48)  评论(2编辑  收藏  举报