杜教筛
杜教筛
前置:数论分块,莫比乌斯反演,狄利克雷卷积,欧拉函数。
对于数论函数 \(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)\) 使用狄利克雷卷积展开为 \(g(d) f(\frac{i}{d})\) 而非 \(f(d) g(\frac{i}{d})\) 的原因是为了构造出 \(S\)。
枚举 \(d\),转换一下式子得,
把 \(g(d)\) 提出来,
根据 \(S(n)\) 的定义,后面这块式子可以变为 \(S(\lfloor \frac{n}{d} \rfloor)\),
为了构造 \(S(n)\),我们把 \(d = 1\) 时的式子拆开来
移项可得:
那么,对于 \(f(n)\),我们只要找到一个合适的数论函数 \(g(n)\) 便能够求解 \(S(n)\)。
莫比乌斯函数
莫比乌斯函数,即 \(\mu(n)\)。
我们令 \(g(n) = 1\)。
至此,便可用数论分块求得。
$\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\)。
至此,我们也能够使用数论分块解决。
$\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}})}\) 的时间复杂度内解决。