数论学习笔记(二):数论函数
数论函数
$\text{If for every value of x,} $
\(\text{y has a completely determined corresponding value,}\)
\(\text{then y is a function of x.}\)
\(—— \text{Johann Dirichlet}\)
基本概念
数论函数:定义域为正整数的函数。
加性函数:若对于任意正整数 \(a, b\),\(\gcd(a, b) = 1\),都有 \(f(ab) = f(a) + f(b)\),则称 \(f\) 为加性函数。
若对于任意正整数 \(a, b\),都有 \(f(ab) = f(a) + f(b)\),则称 \(f\) 为完全加性函数。
积性函数、完全积性函数:见数论学习笔记(一):同余相关
可以发现,对于积性函数 \(f\),\(f(n) = f(1)f(n)\),因此 \(f(1)\) 永远为 \(1\)。
唯一分解定理:任何大于 \(1\) 的正整数都可以唯一分解成有限个质数的乘积,即 \(n = \displaystyle\prod_{i=1}^np_i^{c_i}\)(\(p_i\) 互不相等且均属于素数集 \(\mathbb{P}\))。
常见数论函数
设正整数 \(n = \displaystyle\prod_{i=1}^n p_i^{c_i}\),那么可以给出以下数论函数:
-
单位函数:\(\varepsilon(n) = [n = 1]\),显然,它是完全积性函数。
-
常量函数:\(1(n) = 1\),也很显然,它是完全积性函数。
-
幂函数:\(\operatorname{id}_k(n) = n^k\),当 \(n = 1\) 时记为 \(\operatorname{id}(n)\),此时它被称作恒等函数,它是完全积性函数。
证:对于正整数 \(n, m\),\(\operatorname{id}_k(n)\operatorname{id}_k(m) = n^k m^k = (mn)^k = \operatorname{id}_k(nm)\)
- 除数函数:\(\sigma_k(n) = \displaystyle\sum_{d \mid n} d^k\),当 \(n = 0\) 时记为 \(d(n)\) 或 \(\tau(n)\),此时它表示 \(n\) 的因子个数;当 \(n = 1\) 时记为 \(\sigma(n)\),此时它表示 \(n\) 的因数和,他是积性函数。
证:对于正整数 \(m, n\),当 \(n = m = 1\) 时显然成立。
当 \(n, m\) 不全为 \(1\) 且 \(\gcd(n, m) = 1\) 时,\(\sigma_k(n)\sigma_k(m) = \displaystyle\sum_{d_1 \mid n} d_1^k \sum_{d_2 \mid m} d_2^k = \displaystyle\sum_{d_1 \mid n} \sum_{d_2 \mid m} d_1^k d_2^k = \displaystyle\sum_{d_1 \mid n} \sum_{d_2 \mid m} (d_1d_2)^k\)
\(\because d_1 \mid n\),\(d_2 \mid m\)
\(\therefore\) 设 \(n = ad_1\),\(m = bd_2\)
\(\therefore nm = abd_1d_2\)
\(\therefore (d_1d_2) \mid (nm)\)
\(\because \gcd(n, m) = 1\)
\(\therefore d_1d_2 \neq d_1'd_2'\)
\(\therefore d_1 d_2\) 恰好遍历了 \(nm\) 的所有因子。
\(\therefore\) 原式 \(= \displaystyle\sum_{d \mid nm} d^k = \sigma_k(nm)\)
计算式:
证:当 \(k = 0\) 时,它表示 \(n\) 的因数个数,考虑每个因数中每个质因子出现了多少遍,每个质因子都可以出现 \(0\) 到 \(c_i\) 次,根据乘法原理可以求出。
当 \(k > 0\) 时,还是考虑每个因数中每个质因子出现了多少遍,每个质因子都可以为答案贡献 \(\displaystyle\sum_{j=0}^{c_i} p_i^{jk}\)
\(\because \sigma\) 是积性函数。
\(\therefore \sigma_k(n) = \displaystyle\prod_{i=1}^m\sum_{j=0}^{c_i} p_i^{jk}\)
\(\therefore\) 对它进行等比数列求和,就可以求出等式。
-
欧拉函数:\(\varphi(n) = \displaystyle\sum_{i=1}^n [\gcd(i, n) = 1]\),它表示小于等于 \(n\) 且与 \(n\) 互质的数的个数,它的基本性质详见数论学习笔记(一):同余相关
-
本质不同的质因子个数函数:\(\omega(n) = \displaystyle\sum_{p \in \mathbb{P}} [p \mid n]\),它表示一个数本质不同的质因子个数
(有点废话),他是加性函数
证:对于正整数 \(n, m\),\(\gcd(n, m) = 1\)
当 \(n = 1\) 时,\(\omega(1) = \displaystyle\sum_{p \in \mathbb{P}} [p \mid 1] = 0\)
当 \(n > 1\) 时,
\(\begin{aligned} \omega(nm) &= \displaystyle\sum_{p \in \mathbb{P}} [p \mid nm] \\&= \sum_{p \in \mathbb{P}} [p \mid n] \vee [p \mid m] \\&= \sum_{p \in \mathbb{P}} [p \mid n] + \sum_{p \in \mathbb{P}} [p \mid m] - \sum_{p \in \mathbb{P}} [p \mid n] \wedge [p \mid m] \end{aligned}\)
考虑容斥原理,则有:
\(\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\begin{aligned} &= \displaystyle\sum_{p \in \mathbb{P}} [p \mid n] + \sum_{p \in \mathbb{P}} [p \mid m] - \sum_{p \in \mathbb{P}} [p \mid \gcd(n, m)] \\&= \sum_{p \in \mathbb{P}} [p \mid n] + \sum_{p \in \mathbb{P}} [p \mid m] - \sum_{p \in \mathbb{P}}[p \mid 1] \\&= \sum_{p \in \mathbb{P}} [p \mid n] + \sum_{p \in \mathbb{P}} [p \mid m] \\&= \omega(n) + \omega(m) \end{aligned}\)
- 莫比乌斯函数:
它是积性函数。
证:当 \(n = 1\) 时,\(\mu(n) = 1\)
当 \(n, m\) 中有一个是 \(1\),假设 \(n\) 是 \(1\)
\(\therefore \mu(nm) = \mu(m) = 1 \times \mu(m) = \mu(n)\mu(m)\)
当 \(\exists d > 1, d^2 \mid n\)
\(\therefore d^2 \mid nm\)
\(\therefore \mu(nm) = 0 = 0 \times \mu(m) = \mu(n)\mu(m)\)
其他情况中 \(\mu(n)\mu(m) = (-1)^{\omega(n) }(-1)^{\omega(m)} = (-1)^{\omega(n) + \omega(m)}\)
\(\because \omega\) 是加性函数
\(\therefore\) 原式 \(= (-1)^{\omega(nm)} = \mu(nm)\)
- 总质因数个数函数: \(\Omega(n) = \displaystyle\sum_{p \in \mathbb{P}} \sum_{p^\alpha \mid n} 1(\alpha > 0)\),它表示一个数质数幂因子的个数,它是完全加性函数。
证:首先,当 \(p_i \in \mathbb{P}\) 时,\(\Omega(p_i) \displaystyle\sum_{p \in \mathbb{P}} \sum_{p^\alpha \mid p_i} 1 = 1\)
\(\begin{aligned} \therefore \Omega(np_i) &= \displaystyle\sum_{p \in \mathbb{P}} \sum_{p^\alpha \mid np_i} 1 \\&= \sum_{p \in \mathbb{P} \wedge p \neq p_i} \sum_{p^\alpha \mid np_i} 1 + \sum_{p_i^\alpha \mid np_i} 1 \\&= \sum_{p \in \mathbb{P} \wedge p \neq p_i} \sum_{p^\alpha \mid n} 1 + (\sum_{p_i^\alpha \mid n} 1 + 1) \\&= (\sum_{p \in \mathbb{P} \wedge p \neq p_i} \sum_{p^\alpha \mid n} 1 + \sum_{p_i^\alpha \mid n} 1) + 1 \\&= \sum_{p \in \mathbb{P}} \sum_{p^\alpha \mid n} 1 + 1 \\&= \Omega(n) + \Omega(p_i)\end{aligned}\)
- 刘维尔函数:\(\lambda(n) = -1^{\Omega(n)}\),显然,它是完全积性函数。
狄利克雷卷积
定义
两个数论函数 \(f\) 和 \(g\) 的狄利克雷卷积 \((f \ast g)(n) = \displaystyle\sum_{d \mid n} f(d) g \left(\frac nd \right) = \sum_{xy = n} f(x) g(y)\)
性质
- 交换律:\(f \ast g = g \ast f\)。
证:\((f \ast g)(n) = \displaystyle\sum_{d \mid n} f(d) g \left(\frac nd \right)\)。
考虑到 \(d\) 是 \(n\) 的因子,于是 \(d = \displaystyle\frac{n}{d'}\),那么 \(\displaystyle\frac nd = d'\),则原式 \(= \displaystyle\sum_{d' \mid n} g(d') f \left(\frac{n}{d'} \right) = g \ast f\)。
- 结合律:\((f \ast g) \ast h = f \ast (g \ast h)\)。
证:
\(\begin{aligned} ((f \ast g) \ast h)(n) &= \displaystyle\sum_{d \mid n} \left(\sum_{i \mid d} f(i) g \left(\frac di \right)\right) h \left(\frac nd \right) \\&= \sum_{i \mid n} f(i) \left(\sum_{d = ki \wedge d \mid n} g \left(\frac di \right) h \left(\frac nd \right)\right) \\&= \sum_{i \mid n} f(i) \left(\sum_{k \mid \frac ni} g(k) h \left(\frac{\frac ni}{k} \right) \right) \\&= f \ast (g \ast h)\end{aligned}\)
- 分配律:\((f + g) \ast h = f \ast h + g \ast h\)。
证:
\(\begin{aligned} ((f + g) \ast h)(n) &= \displaystyle\sum_{d \mid n} (f(d) + g(d)) h \left( \frac nd \right) \\&= \sum_{d \mid n} f(d) h \left(\frac nd \right) + \sum_{d \mid n} g(d) h \left(\frac nd \right) \\&= f \ast h + g \ast h\end{aligned}\)
- 单位元:\(f \ast \varepsilon = \varepsilon \ast f = f\)。
证:\(\varepsilon \ast f = \displaystyle\sum_{d \mid n} [d = 1] f \left(\frac nd \right) = f(n)\)
现在我们可以发现,\(\varepsilon\) 是狄利克雷卷积的单位元,因此对于一个积性函数 \(f\),若存在积性函数 \(g\) 使得 \(f \ast g = \varepsilon\),则 \(g\) 为 \(f\) 的狄利克雷逆。
- 积性函数 \(f\) 存在狄利克雷逆当且仅当 \(f(1) \neq 0\)。
证:设 \(f \ast g = \varepsilon\),若 \(f(1) = 0\),则 \(f(1)g(1) = 0\),但是 \(f(1)g(1) = [1 = 1] = 1\),矛盾,则此时不存在狄利克雷逆。
假设 \(f(1) \neq 0\),则 \(\displaystyle\sum_{d \mid n} f(d) g \left(\frac nd \right) = 0\),于是 \(g(n) = - \displaystyle\frac{\displaystyle\sum_{d \mid n \wedge d \neq n} g(d) f \left(\frac nd \right)}{f(1)}\),因此可以递推出 \(g\)。
- 积性函数的狄利克雷逆仍是积性函数。
证:考虑数学归纳法。
设 \(f \ast g = \varepsilon\),先考虑边界情况,因为 \(g(1) = \displaystyle\frac{1}{f(1)} = 1\),因此 \(g(1)g(1) = g(1)\),边界情况成立。
对于 \(n, m > 1\) 且 \(\gcd(n, m) = 1\),假设对于所有 \(xy < nm\) 且 \(\gcd(x, y) = 1\),都有 \(g(x)g(y) = g(xy)\),现在来证明 \(g(m)g(n) = g(mn)\)。
根据上一条推出的递推式,\(g(nm) = - \displaystyle\sum_{d \mid nm \wedge d \neq nm} g(d) f \left(\frac{nm}{d} \right)\)。
由于此时 \(d < nm\),于是原式会变成 \(- \displaystyle\sum_{a \mid n, b \mid m, ab \neq nm} g(a) g(b) f \left(\frac na \right) f \left(\frac nb \right)\),将式子加上 \(f(1)^2 g(n) g(m)\) 再减去,可以得到 \(f(1)^2 g(n) g(m) - \displaystyle\sum_{a \mid n} g(a) f \left(\frac na \right) \sum_{b \mid m} g(b) f \left(\frac mb \right)\)。
后方的式子 \(= \displaystyle\sum_{a \mid n} g(a) f \left(\frac na \right)[m = 1]\),由于 \(m > 1\),因此此项为 \(0\),于是 \(g(nm) = f(1)^2 g(n) g(m) = g(n)g(m)\),符合数学归纳法,证明成立。
- 两个积性函数的狄利克雷卷积仍是积性函数。
证:设 \(f \ast g = h\),若 \(\gcd(n, m) = 1\),则
\(\begin{aligned} h(n)h(m) &= \left(\displaystyle\sum_{d_1 \mid n} f(d_1) g \left(\frac{n}{d_1} \right) \right)\left(\sum_{d_2 \mid n} f(d_2) g \left(\frac{n}{d_2} \right) \right) \\&= \sum_{d_1d_2 \mid n} f(d_1)f(d_2) g \left(\frac{n}{d_1} \right) g \left(\frac{n}{d_2} \right) \\&= \sum_{d_1d_2 \mid n} f(d_1d_2) g \left(\frac{n}{d_1d_2} \right) \\&= \sum_{d \mid n} f(d) g \left(\frac nd \right) \\&= h(nm)\end{aligned}\)
数论函数之间的关系
- \(\mu \ast 1 = \varepsilon\)
证:
\(\begin{aligned} (\mu \ast 1)(n) &= \displaystyle\sum_{d \mid n} \mu(d) 1 \left(\frac nd \right) \\&= \sum_{d \mid n} \mu(d) \\&= \sum_{i=0}^{\omega(n)} \binom{\omega(n)}{i} (-1)^i \\&= [1 + (-1)]^k\end{aligned}\)
\(\because [1 + (-1)]^k = \begin{cases} 1 & : k = 0\\ 0 & : k \neq 0 \end{cases}\)
\(\begin{aligned} \therefore [1 + (-1)]^k &= [k = 0] \\&= [n = 1] \\&= \varepsilon(n)\end{aligned}\)
- \(\varphi \ast 1 = \operatorname{id}\)
证:我们已经在数论学习笔记(一):同余相关中用一个比较取巧的方法证明了这个式子,现在我们再用狄利克雷卷积来证明。
因为 \(\varphi\) 和 \(\operatorname{id}\) 都是积性函数,因此,只用证明该式子在质数幂 \(p^k\) 处成立,就可以通过唯一分解定理,将若干个 \(p^k\) 乘起来得到其它正整数。
\(\begin{aligned} (\varphi \ast 1)(p^k) &= \displaystyle\sum_{d \mid p^k} \varphi(d) \\ &= \sum_{i = 0}^k \varphi(p^i) \\&= 1 + \sum_{i = 1}^k p^i - p^{i - 1} \\&= p^k\end{aligned}\)
- \(\mu \ast \operatorname{id} = \varphi\)
证:由于我们知道了 \(\varphi \ast 1 = \operatorname{id}\),我们在两边同时再卷上一个 \(\mu\),可以得到 \(\varphi \ast 1 \ast \mu = \operatorname{id} \ast \mu\),又因为 \(1 \ast \mu = \varepsilon\),而 \(\varepsilon \ast \varphi = \varphi\),因此 \(\mu \ast \operatorname{id} = \varphi\)。
- \(1 \ast 1 = d = \sigma_0\)
证:\((1 \ast 1)(n) = \displaystyle\sum_{d \mid n} 1 = d(n)\)
- \(1 \ast \operatorname{id}_k = \sigma_k\)
证:\((1 \ast \operatorname{id}_k)(n) = \displaystyle\sum_{d \mid n} d^k = \sigma_k(n)\)
点积
整除分块
这是数论题最常见的做法。组合数推式子一般推到所有因子可以预处理,而数论推式子一般就推到所有因子可以求前缀和或可以整除分块。
考虑一共有多少个不同的 \(\lfloor \displaystyle\frac nx \rfloor\),分以下两种情况讨论:
-
若 \(x \leq \sqrt n\),则不同的 \(x\) 只有 \(O(\sqrt n)\) 种,于是不同的 \(\lfloor \displaystyle\frac nx \rfloor\) 也只有 \(O(\sqrt n)\) 种。
-
若 \(x > \sqrt n\),则 \(\lfloor \displaystyle\frac nx \rfloor \leq \sqrt n\),因此 \(\lfloor \displaystyle\frac nx \rfloor\) 也只有 \(O(\sqrt n)\) 种。
于是我们就可以很容易求出这 \(O(\sqrt n)\) 种不同的 \(\lfloor \displaystyle\frac nx \rfloor\):
for(int l = 1, r; l <= n; l = r + 1)
r = n / (n / l);
于是对于每个 \(x \in [l, r]\),都有 \(\lfloor \displaystyle\frac nx \rfloor = \lfloor \displaystyle\frac nl \rfloor\)。
莫比乌斯反演
首先,莫比乌斯反演是一类特殊的子集反演,详见组合数学学习笔记(二):鸽巢原理、容斥及反演。莫比乌斯反演式子如下:
证:
现在可以发现,由于 \(\mu \ast 1 = \varepsilon\),那么 \(\displaystyle\sum_{d \mid \frac nk} \mu(d) = \left[\frac nk = 1\right]\),于是只有 \(k\) 为 \(n\) 时值为 \(1\),那么原式就等于 \(g(n)\),证明成立。
将莫比乌斯反演与子集反演的式子进行对比:
不难发现二者有一些相似之处:考虑记 \(S\) 为 \(n\) 的所有素因数的多重集,那么枚举因数 \(d \mid n\) 实际上就是枚举了一个子多重集 \(T \in S\)。因此莫比乌斯反演的实质就是子多重集反演,而 \(\mu\) 就是这个反演的系数。
解:非常经典的莫比乌斯反演的题目,我们要求 \(\displaystyle\sum_{i = 1}^n \sum_{j = 1}^n \gcd(i, j)\)。
首先我们先改变枚举方式,先枚举最大公约数 \(d\),再枚举任意两个数的最大公约数是否为 \(d\),那么原式变成 \(\displaystyle\sum_{d \geq 1} d \sum_{i = 1}^n \sum_{j = 1}^n [\gcd(i, j) = d]\)。
考虑到若 \(\gcd(i, j) = d\),那么 \(\gcd \left( \displaystyle\frac id, \frac jd\right) = 1\),于是原式就变成了 \(\displaystyle\sum_{d \geq 1} d \sum_{i = 1}^{\lfloor \frac nd \rfloor} \sum_{j = 1}^{\lfloor \frac nd \rfloor} [\gcd(i, j) = 1]\)。
现在可以发现 \([\gcd(i, j) = 1]\) 就是 \(\varepsilon\),因为 \(\mu \ast 1 = \varepsilon\),于是式子再次化成 \(\displaystyle\sum_{d \geq 1} d \sum_{i = 1}^{\lfloor \frac nd \rfloor} \sum_{j = 1}^{\lfloor \frac nd \rfloor} \sum_{k \mid \gcd(i, j)} \mu(k)\)。
考虑到 \(k \mid \gcd(i, j) \iff k \mid i \wedge k \mid j\),于是原式 \(= \displaystyle\sum_{d \geq 1} d \sum_{k \geq 1} \mu(k) \sum_{i = 1}^{\lfloor \frac nd \rfloor} [k \mid i] \sum_{j = 1}^{\lfloor \frac nd \rfloor} [k \mid j] = \displaystyle\sum_{d \geq 1} d \sum_{k \geq 1} \mu(k) \left\lfloor \frac{\lfloor \frac nd \rfloor}{k} \right\rfloor^2\)。
由于 \(\left\lfloor \displaystyle\frac{\lfloor \frac nd \rfloor}{k} \right\rfloor = \left\lfloor \displaystyle\frac{n}{dk} \right\rfloor\),于是设 \(T = dk\),那么原式就会变成 \(\displaystyle\sum_{T = 1}^n \left\lfloor \frac nT \right\rfloor^2 \left(\sum_{dk = T} \mu(k) d\right)\),注意到 \(\displaystyle\sum_{dk = T} \mu(k) d = \mu \ast \operatorname{id} = \varphi\),于是这个式子最终化简成 \(\displaystyle\sum_{T = 1}^n \left\lfloor \frac nT \right\rfloor^2 \varphi(T)\),于是求出 \(\varphi\) 的前缀和,就可以用整除分块来做这道题目了。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 4e6 + 9;
int vis[N], prime[N], phi[N], sum[N], n, ans;
void get_phi(){
phi[1] = 1;
int cnt = 0;
for(int i = 2; i < N; i++){
if(!vis[i]){
vis[i] = i;
prime[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; j < cnt && i * prime[j] < N; j++){
vis[i * prime[j]] = prime[j];
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
for(int i = 1; i < N; i++)
sum[i] = sum[i - 1] + phi[i];
}
signed main(){
get_phi();
scanf("%lld", &n);
for(int l = 1, r; l <= n; l = r + 1){
r = n / (n / l);
ans += (n / l) * (n / l) * (sum[r] - sum[l - 1]);
}
printf("%lld", ans);
return 0;
}
与上一道题一样,只是这次要求的式子变成了 \(\displaystyle\sum_{T = 1}^n \left\lfloor \frac nT \right\rfloor \left\lfloor \frac mT \right\rfloor \varphi(T)\),于是我们需要对 \(m\) 和 \(n\) 都整除分块,最后取 \(\min\) 就可以了。
注意最后这道题要 \(\times 2\) 再减 \(n \times m\)。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 4e6 + 9;
int vis[N], prime[N], phi[N], sum[N], n, m, ans;
void get_phi(){
phi[1] = 1;
int cnt = 0;
for(int i = 2; i < N; i++){
if(!vis[i]){
vis[i] = i;
prime[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; j < cnt && i * prime[j] < N; j++){
vis[i * prime[j]] = prime[j];
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
for(int i = 1; i < N; i++)
sum[i] = sum[i - 1] + phi[i];
}
signed main(){
get_phi();
scanf("%lld%lld", &n, &m);
for(int l = 1, r; l <= n && l <= m; l = r + 1){
r = min(n / (n / l), m / (m / l));
ans += (n / l) * (m / l) * (sum[r] - sum[l - 1]);
}
printf("%lld", ans * 2 - n * m);
return 0;
}
这道题要求 \(\displaystyle\sum_{i = 1}^{n - 1} \sum_{j = 1}^{n - 1} [\gcd(i, j) = 1] + 2\),我们来求他的一般形式 \(\displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m} [\gcd(i, j) = 1]\)。
还是大力推式子:
\( \begin{aligned} \displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m} [\gcd(i, j) = 1] &= \sum_{i = 1}^{n} \sum_{j = 1}^{m} \sum_{d \mid \gcd(i, j)} \mu(d) \\&= \sum_{d \geq 1} \mu(d) \sum_{i = 1}^n[d \mid i] \sum_{j = 1}^m [d \mid j] \\&= \sum_{d \geq 1} \mu(d) \left\lfloor\frac nd \right\rfloor \left\lfloor\frac md \right\rfloor \end{aligned} \)
依然先求出 \(\mu\) 的前缀和,然后就可以用整除分块做了。
完整代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 9;
int vis[N], prime[N], mu[N], sum[N], ans;
void get_mu(){
mu[1] = 1;
int cnt = 0;
for(int i = 2; i < N; i++){
if(!vis[i]){
vis[i] = i;
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt && i * prime[j] < N; j++){
vis[i * prime[j]] = prime[j];
if(i % prime[j] == 0)
break;
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1; i < N; i++)
sum[i] = sum[i - 1] + mu[i];
}
int main(){
get_mu();
int n;
scanf("%d", &n);
n--;
if(!n){
printf("0\n");
return 0;
}
for(int l = 1, r; l <= n; l = r + 1){
r = n / (n / l);
ans += (n / l) * (n / l) * (sum[r] - sum[l - 1]);
}
printf("%d", ans + 2);
return 0;
}
这题变成求 \(\displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m} \operatorname{lcm}(i, j)\),由于 \(\operatorname{lcm}(i, j) = \displaystyle\frac{ij}{\gcd(i, j)}\),于是我们求的变成了 \(\displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m} \frac{ij}{\gcd(i, j)}\)。
依然枚举最大公因数 \(d\),于是要求 \(\displaystyle\sum_{d \geq 0} d \sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = d] \frac{ij}{d}\),由于若 \(\gcd(i, j) = d\),那么 \(d \mid i\) 且 \(d \mid j\),那么将 \(i\) 和 \(j\) 的上界都除以 \(d\),那么原式 \(= \displaystyle\sum_{d \geq 1} d \sum_{i = 1}^{\lfloor \frac nd \rfloor} \sum_{j = 1}^{\lfloor \frac md \rfloor} [\gcd(i, j) = 1]ij\),对 \(\left\lfloor \displaystyle\frac nd \right\rfloor\) 和 \(\left\lfloor \displaystyle\frac md \right\rfloor\) 整除分块后,就只用考虑 \(\displaystyle\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = 1]ij\) 怎么求。
记 \(S(n) = \displaystyle\sum_{i = 1}^n i = \frac{n(n + 1)}{2}\),依然大力推式子:
\( \begin{aligned} \displaystyle\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = 1]ij &= \sum_{i = 1}^n \sum_{j = 1}^m ij \sum_{k \mid \gcd(i, j)} \mu(k) \\&= \sum_{i = 1}^n \sum_{j = 1}^m (ak)(bk) \sum_{k \mid \gcd(i, j)} \mu(k) \\&= \sum_{k = 1}^n \mu(k) k^2 \sum_{i = 1}^{\lfloor \frac nd \rfloor} \sum_{j = 1}^{\lfloor \frac md \rfloor} ij \\&= \sum_{k = 1}^n \mu(k) k^2 S(\left\lfloor \frac nd \right\rfloor) S(\left\lfloor \frac md \right\rfloor) \end{aligned} \)
现在若能预处理积性函数 \(x^2 \mu(x)\)的前缀和,再套一个整除分块就可以做了,不过现在是一个整除分块套整除分块的形式,复杂度为 \(\displaystyle\int_1^{\sqrt n} \sqrt x \mathrm dx = O(n^{\frac 34})\),不能通过此题,于是继续化简。
我们将 \(\displaystyle\sum_{i = 1}^n \sum_{j = 1}^m [\gcd(i, j) = 1]ij\) 化简后的式子代回原式,可以得到 \(\displaystyle\sum_{d \geq 1} d \sum_{k = 1}^{\lfloor \frac nd \rfloor}\mu(k) k^2 S(\left\lfloor \frac{n}{dk} \right\rfloor) S(\left\lfloor \frac{m}{dk} \right\rfloor)\)。
设 \(T = dk\),于是原式 \(= \displaystyle\sum_{T = 1}^n S(\left\lfloor \frac nT \right\rfloor) S(\left\lfloor \frac mT \right\rfloor) \sum_{kd = T} \mu(k) k^2 d\),可以发现式子 \(\displaystyle\sum_{kd = T} \mu(k) k^2 d\) 中 \(\mu(k) k^2\) 是积性函数(狄利克雷卷积性质 \(7\)),而 \(k\) 是 \(\operatorname{id}(k)\),两个积性函数的点积也是积性函数,因此这也是积性函数,可以线性筛筛出,于是 \(O(n)\) 预处理 \(O(\sqrt n)\) 计算即可通过此题。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7 + 9, MOD = 20101009;
int vis[N], prime[N], sum[N], f[N], ans, n, m;
void get_f(){
f[1] = 1;
int cnt = 0;
for(int i = 2; i < N; i++){
if(!vis[i]){
vis[i] = i;
prime[cnt++] = i;
f[i] = 1 - i + MOD;
}
for(int j = 0; j < cnt && i * prime[j] < N; j++){
vis[i * prime[j]] = prime[j];
if(i % prime[j] == 0){
f[i * prime[j]] = f[i];
break;
}
f[i * prime[j]] = f[i] * f[prime[j]] % MOD;
}
}
for(int i = 1; i < N; i++)
sum[i] = (sum[i - 1] + i * f[i] % MOD) % MOD;
}
signed main(){
get_f();
scanf("%lld%lld", &n, &m);
if(n > m)
swap(n, m);
for(int l = 1, r; l <= n && l <= m; l = r + 1){
r = min(n / (n / l), m / (m / l));
ans = (ans + ((n / l) * (n / l + 1) / 2 % MOD) * ((m / l) * (m / l + 1) / 2 % MOD) % MOD * (sum[r] - sum[l - 1]) % MOD + MOD) % MOD;
}
printf("%lld", ans);
return 0;
}
这真的是基础练习题吗?
线性筛积性函数与应用
高级筛法
这两个算法都可以快速求积性函数的前缀和。
杜教筛
对于一个积性函数 \(f\),我们要求 \(S(n) = \displaystyle\sum_{i = 1}^n f(i)\)。
我们再找到一个积性函数 \(g\),求出它与 \(f\) 的狄利克雷卷积 \(f \ast g = \displaystyle\sum_{d \mid n} f(n) g \left(\frac nd \right)\),我们求出这个函数的前缀和 \(\displaystyle\sum_{i = 1}^n (f \ast g)(i) = \sum_{i = 1}^n \sum_{d \mid i} g(d) f \left(\frac id \right)\)。
交换求和顺序,先枚举 \(d\),由于 \(d \mid i\),因此原式再次变成 \(\displaystyle\sum_{d = 1}^n g(d) \sum_{i = kd \wedge i \leq n} f \left(\frac id \right) = \sum_{d = 1}^n g(d) \sum_{i = kd \wedge i \leq n} f(k)\),由于 \(k\) 最多达到 \(\left\lfloor \displaystyle\frac nd \right\rfloor\),于是原式再次变成 \(\displaystyle\sum_{d = 1}^n g(d) \sum_{i = 1}^{\lfloor \frac nd \rfloor} f(i) = \sum_{i = 1}^n g(i) S \left(\left\lfloor\frac ni \right\rfloor\right)\)。
由于 \(S(n) = g(1)S(n)\),于是 \(S(n)\) 可以写成 \(\displaystyle\sum_{i = 1}^n g(i) S \left(\left\lfloor\frac ni \right\rfloor\right) - \sum_{i = 2}^n g(i) S \left(\left\lfloor\frac ni \right\rfloor\right)\)。
我们令 \(h = f \ast g\),于是 \(S(n) = \displaystyle\sum_{i = 1}^n h(i) - \sum_{i = 2}^n g(i) S \left(\left\lfloor\frac ni \right\rfloor\right)\),于是,如果我们能快速求出 \(h\) 和 \(g\) 的前缀和,就可以通过整除分块来算出 \(S(n)\)。
具体地,由于不同的 \(i\),一共有 \(\sqrt n\) 个不同的 \(\left\lfloor\displaystyle\frac ni \right\rfloor\),于是我们通过记忆化搜索的方法,不断递归求出 \(S \left(\left\lfloor\displaystyle\frac ni \right\rfloor\right)\),那么时间复杂度就为 \(O(\sqrt n) + \displaystyle\sum_{k = 1}^{\lfloor\sqrt n\rfloor} O(\sqrt k) + \sum_{k = 2}^{\lfloor\sqrt n\rfloor} O\left(\sqrt{\frac nk}\right) = O\left(\int_{0}^{\sqrt n} \left(\sqrt x + \sqrt{\frac nx}\right) \mathrm dx \right) = O\left(n^{\frac 34} \right)\)。
考虑到 \(n\) 较小的时候可以直接通过线性筛筛出答案,不需要递归下去。假设我们将前 \(m\) 个数预处理了,那么时间复杂度会变成 \(O(m) + \displaystyle\sum_{k = 1}^{\lfloor \frac nm \rfloor} O\left(\sqrt{\frac nk} \right) = O\left(O(m) + \int_0^{\frac nm} \sqrt{\frac nx} \mathrm dx \right) = O\left(O(m) + \frac{n}{\sqrt m} \right)\),通过均值不等式可以知道当 \(m = n^{\frac 23}\) 时时间复杂度最优,为 \(O(n^{\frac 23})\)。
以洛谷的杜教筛模板为例。
我们来试着筛出 \(\varphi\) 和 \(\mu\) 的前缀和。
注意到 \(\mu \ast 1 = \varepsilon\),带入杜教筛的式子中,可以得到 \(S(n) = 1 - \displaystyle\sum_{i = 2}^{n} 1(i) S \left(\left\lfloor\frac ni \right\rfloor\right)\),由于 \(1(i)\) 的前缀和就是 \(i\),于是可以用杜教筛求解。
对于函数 \(\varphi\) 有两种求法:
法1
\(\displaystyle\sum_{i = 1}^n \varphi(i) = \sum_{i = 1}^n \sum_{j = 1}^n [\gcd(i, j) = 1]\)。这个之前求过了,答案为 \(\displaystyle\sum_{d \geq 1} \mu(d) \left\lfloor\frac nd \right\rfloor^2\),于是可以先筛 \(\mu\) 再转化为 \(\phi\)。
法二
注意到 \(\varphi \ast 1 = \operatorname{id}\),将其带入杜教筛的式子中可以得到 \(S(n) = \displaystyle\frac{n(n + 1)}{2} - \sum_{i = 2}^n1(i) S \left(\left\lfloor\frac ni \right\rfloor\right)\),依然可以通过杜教筛来求。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e6 + 9;
int prime[N], mu[N], phi[N], sum1[N], sum2[N];
bool vis[N];
unordered_map <int, int> summu, sumphi;
void init(){
int cnt = 0;
vis[0] = vis[1] = 1;
mu[1] = phi[1] = 1;
for(int i = 2; i < N; i++){
if(!vis[i]){
prime[cnt++] = i;
mu[i] = -1;
phi[i] = i - 1;
}
for(int j = 0; j < cnt && i * prime[j] < N; j++){
vis[i * prime[j]] = 1;
if(i % prime[j]){
mu[i * prime[j]] = -mu[i];
phi[i * prime[j]] = phi[i] * phi[prime[j]];
} else {
mu[i * prime[j]] = 0;
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
for(int i = 1; i < N; i++){
sum1[i] = sum1[i - 1] + mu[i];
sum2[i] = sum2[i - 1] + phi[i];
}
}
int getsmu(int x){
if(x < N)
return sum1[x];
if(summu[x])
return summu[x];
int ans = 1;
for(int l = 2, r; l <= x; l = r + 1){
r = x / (x / l);
ans -= (r - l + 1) * getsmu(x / l);
}
return summu[x] = ans;
}
int getphi(int x){
if(x < N)
return sum2[x];
if(sumphi[x])
return sumphi[x];
int ans = x * (x + 1) / 2;
for(int l = 2, r; l <= x; l = r + 1){
r = x / (x / l);
ans -= (r - l + 1) * getphi(x / l);
}
return sumphi[x] = ans;
}
signed main(){
init();
int t;
scanf("%lld", &t);
while(t--){
int n;
scanf("%lld", &n);
printf("%lld %lld\n", getphi(n), getsmu(n));
}
return 0;
}
Powerful Number
对于正整数 \(n\),记 \(n\) 的质因数分解为
\(n = \displaystyle\prod_{i = 1}^m p_i^{e_i}\)。\(n\) 是 \(\text{Powerful Number}\)(简称 \(PN\)) 当且仅当 \(\forall 1 \leq i \leq m, e_{i} > 1\)。
\(\text{Powerful Number}\) 有如下性质:
- 所有的 \(PN\) 都可以写成 \(a^2 b^3\) 的形式;
证:若 \(e_i\) 是偶数,直接合并进 \(a^2\);如果 \(e_i\) 是奇数,那么 \(e_i\) 至少为 \(3\),于是先将 \(p_i^3\) 合并进 \(b^3\),再将剩下的合并进 \(a^2\)。
- \(n\) 以内的 \(PN\) 有 \(O(\sqrt n)\) 个。
证:考虑先枚举 \(a^2b^3\) 中的 \(a\)(\(1 \leq a \leq \sqrt n\)),再枚举符合条件的 \(b\) 的数量,于是 \(PN\) 的个数约为 \(\displaystyle\int_{i = 1}^{\sqrt n} \sqrt[3]{\frac{n}{x^2}} \mathrm dx = O(\sqrt n)\)。
正题
参考资料
-
王hx、黄yy、张hr 的课件
-
初等数论学习笔记 III:数论函数与筛法 Alex_wei
-
【数学】加性函数与积性函数 mangoworld
-
杜教筛(+贝尔级数+powerful number) command_block
-
炫酷反演魔术 command_block
本文来自博客园,作者:Orange_new,转载请注明原文链接:https://www.cnblogs.com/JPGOJCZX/p/18422868

浙公网安备 33010602011771号