Dirichlet 卷积
狄克卷积
狄利克雷卷积
对于积性函数 \(f(x)\) 和 \(g(x)\),定义 \(h = f * g\),那么:
积性函数定义
若对于 \(\forall a, b\) 且 \(\gcd(a, b) = 1\),有 \(f(ab) = f(a) f(b)\),那么 \(f(x)\) 为积性函数。
性质
-
若 \(f\) 和 \(g\) 皆为积性则 \(f * g\) 也为积性。
-
所有积性函数都可以利用线性筛筛出值。
数论函数
注意数论函数全是积性函数,本文也只讨论积性函数。
单位根函数 \(\epsilon(x)\)
显然 \(\forall f, f * \epsilon = \epsilon * f = f\)。
幂函数 \(Id_k(x)\)
\(Id_k(x) = x^k\)。特别的,\(Id_1(x) = x\),\(Id_0(x) = 1\)。\(Id_0(x)\) 被称为常函数,简记为 \(I\)。
\(I(x)\)
对于 \(\forall f\),有:
欧拉函数 \(\varphi(x)\)
\(\varphi(x)\) 是小于等于 \(x\) 的正整数中与 \(x\) 互质的数的个数。
贝尔级数 / 狄利克雷生成函数
设 \(f(x)\),那么对于任意质数 \(p\) 其贝尔级数为 \(F_p (x)\),有:
莫比乌斯反演
我们假设 \(I\) 的逆元为 \(\mu\),那么有:
那么我们现在来求 \(\mu\) 的值。设 \(F_p (x)\) 为 \(I\) 的贝尔级数,显然:
根据 \(I * \mu = \epsilon\) 我们可以求出 \(\mu\) 的贝尔级数 \(G_p(x)\):
所以对于 \(\mu(x)\) 和任意质数 \(p\) 显然有:
那么利用积性函数的性质求出 \(\mu(x)\) 在每个位置的值为:
对于任意积性函数都可以使用贝尔级数求出其逆。
那么对于 \(f * I = g\),我们有:
这就是莫比乌斯反演。我们把它写成公式,对于 \(\forall f(x), g(x)\),若存在关系:
那么有:
可利用于容斥或是推式子。
数论函数递推关系式
假设 \(f \rightarrow g\) 的关系代表 \(f * I = g\) 且 \(g * \mu = f\),那么有:
杜教筛
对于 \(h(x) = \sum_{d \mid x} f(d) g(\frac n d)\),如果可以快速求出 \(\sum_{x = 1} ^ {\forall n} h(x)\) 和 \(\sum_{x = 1} ^ {\forall n} g(x)\),那么就可以利用杜教筛在 \(O(n ^ \frac 2 3)\) 的时间复杂度内求出 \(\sum_{x = 1} ^ {\forall n} f(x)\)。
我们列出等式:
反一下:
我们设 \(s(x) = \sum_{i = 1} ^ x f(i)\),那么我们要求的就是 \(s(n)\),带入得:
移项,得:
数论分块并记忆化搜索即可。
洛谷模板的代码
const int mod = 998244353, maxn = 5 * 1e6;
ll phi[maxn], mu[maxn];
unordered_map <ll, ll> sumphi, summu;
vector <ll> prime;
bool vis[maxn];
void pre() {
if(mu[1]) AC;
phi[1] = mu[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!vis[i]) {
prime.push_back(i);
vis[i] = true;
phi[i] = i - 1;
mu[i] = -1;
}
for(int p : prime) {
if((ll) i * p >= maxn) break;
if(i % p == 0) {
vis[i * p] = true;
mu[i * p] = 0;
phi[i * p] = phi[i] * p;
break;
}
vis[i * p] = true;
mu[i * p] = -mu[i];
phi[i * p] = phi[i] * (p - 1);
}
phi[i] += phi[i - 1];
mu[i] += mu[i - 1];
}
}
il ll sphi(ll n) {
if(n < maxn) return phi[n];
if(sumphi.count(n)) return sumphi[n];
ll res = n * (n + 1) / 2;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * sphi(n / l);
}
sumphi[n] = res;
return res;
}
il ll smu(ll n) {
if(n < maxn) return mu[n];
if(summu.count(n)) return summu[n];
ll res = 1;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * smu(n / l);
}
summu[n] = res;
return res;
}
ll n;
void ACehomoxue() {
pre();
cin >> n;
cout << sphi(n) << ' ' << smu(n);
el;
}

浙公网安备 33010602011771号