数论 $\textbf{Number Theory}$
常见数论函数
欧拉函数 \(\varphi(x)\):积性,表示不超过 \(x\) 且与 \(x\) 互质的数的个数。
单位函数 \(\varepsilon(x)\):完全积性,定义 \(\varepsilon(x)=[x=1]\)。
恒等函数 \(\text{id}_k(x)\):完全积性,定义 \(\text{id}_k(x)=x^k\),当 \(k=1\) 时也叫做标号函数,可写为 \(\text{id}(x)=x\)。
常数函数 \(\mathbb{1}(x)\):完全积性,定义 \(\mathbb{1}(x)=1\)。
除数函数 \(\sigma_k(x)\):定义 \(\sigma_k(x) = \displaystyle\sum_{\substack{d|n}}d^k\),当 \(k=0\) 时可写作 \(d(x)\),称为因数个数函数;当 \(k=1\) 时可写作 \(\sigma(x)\),称为因数和函数。
莫比乌斯函数 \(\mu(x)\):积性,定义 \(\mu(x)=\begin{cases}1,\ \ \ \ \ \ \ \ \ \ \ \ x=1\\ 0,\ \ \ \ \ \ \ \ \ \ \ \ \exists\ d>1,d^2|n\\ (-1)^{\omega(x)},\text{otherwise.}\end{cases}\),其中 \(\omega(x)\) 表示 \(x\) 的不同质因子个数,\(\omega(x)\) 是一个加性函数。
数论中的加性函数指:对于一个数论函数 \(f\),当整数 \(a\perp b\) 时若满足 \(f(ab) = f(a) + f(b)\),则 \(f\) 为加性函数。
\(\text{Dirichlet}\) 卷积
对于两个数论函数 \(f\) 与 \(g\),定义 \(f\) 与 \(g\) 的狄利克雷卷积为:
记为 \(h=f*g\)。
狄利克雷卷积运算满足交换律、结合律与加法结合律(即 \((f+g)*h=f*h+g*h\))。
等式的性质:\(f=g\) 的充要条件是 \(f*h=g*h\),且 \(h(1)\ne 0\)。
狄利克雷卷积单位元 \(\varepsilon\):对于任何数论函数 \(f\),都有 \(f * \varepsilon=f\)。
数论函数的逆元:若两数论函数 \(f,g\) 满足 \(f*g=\varepsilon\),则称 \(f\) 为 \(g\) 的逆元,或称 \(g\) 为 \(f\) 的逆元。
性质
对于两积性数论函数 \(f\) 与 \(g\),其狄利克雷卷积 \(h = f*g\) 也是积性函数。
常见卷积
此类卷积会在后面的莫比乌斯反演中大量运用。
\(\text{Dirichlet}\) 前缀和
对于一个数列 \(\{a_i\}\),其狄利克雷前缀和 \(\{b_i\}\) 定义为 \(b_k=\displaystyle\sum_{i|k}a_i\)。
若要求一个数列的 \(\text{Dirichlet}\) 前缀和,只需先用线性筛筛出下标范围内的所有质数,再枚举质数的倍数求和即可,时间复杂度与埃氏筛相同,即 \(O(n\log\log n)\)。
void Linear_Sieve() {
for (int i = 2; i <= n; i++) {
if (!vis[i]) {
prime[++tot] = i;
}
for (int j = 1; j <= tot && i * prime[j] <= n; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
for (int i = 1; i <= tot; i++) {
for (int j = 1; prime[i] * j <= n; j++) {
a[prime[i] * j] += a[j];
}
}
}
\(\text{Möbius}\) 反演
若两数论函数 \(f,g\) 满足以下关系:
则称 \(f\) 为 \(g\) 的 \(\text{Möbius}\) 变换,\(g\) 为 \(f\) 的 \(\text{Möbius}\) 反演。
这里容易看出,\(f=g*\mathbb{1}\)。
\(\text{Möbius}\) 反演的常见形式是 \(f=\varepsilon,g=\mu\) 的情况。
\(\text{Examples:}\)
求
考虑对式子作下列变换:
第一行,枚举 \(\gcd(i,j)\) 的所有可能取值。
第二行,将 \(k\) 提出来。
第三行,观察到 \(\varepsilon(\gcd(i,j))=[\gcd(i,j)=1]\),那么运用 \(\text{Möbius}\) 反演得到 \([\gcd(i,j)=1]=\varepsilon(\gcd(i,j))=\displaystyle\sum_{d|\gcd(i,j)}\mu(d)\)。
第四行,再次枚举 \(\gcd(i,j)\),观察到若 \(d|\gcd(i,j)\) 则必然有 \(d|i\) 且 \(d|j\)。
第五行,改变枚举顺序。
第六行,观察到 \([1,\left\lfloor\frac{n}{k}\right\rfloor]\) 范围内 \(d\) 的倍数只有 \(\left\lfloor\frac{n}{kd}\right\rfloor\) 个。
//上面的过程好像有问题,懒得改了。
最后,线性筛出 \(\mu\) 的值,整除分块即可,时间复杂度 \(O(n\sqrt n)\)。
本题还有不用反演的做法:利用 \(\varphi\) 的性质,这里不赘述,时间复杂度也为 \(O(n\sqrt n)\)。
下面是 \(\text{Möbius}\) 反演板子题:
求
比刚刚那题一目了然,但刚刚用 \(\varphi\) 的 \(O(Tn\sqrt n)\) 的做法无法通过,只能用反演做法。
化简得到:
此时不能再枚举 \(p\),因为枚举 \(p\) 的时间复杂度还是 \(O(Tn\sqrt n)\) 的。
考虑设 \(C=pd,p\in\text{prime}\),再枚举 \(C\),则原式化为:
预处理后一部分,整除分块即可,时间复杂度 \(O(n+T\sqrt n)\)。
//Made By Cuset. 喵喵~
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int MAXN = 1e7 + 5;
ll mu[MAXN], prime[MAXN], f[MAXN], tot, fsum[MAXN], n, m, t;
bool vis[MAXN];
void Linear_Sieve() {
mu[1] = 1;
for (int i = 2; i <= MAXN - 5; i++) {
if (!vis[i]) {
prime[++tot] = i;
mu[i] = -1;
}
for (int j = 1; j <= tot && i * prime[j] <= MAXN - 5; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
else mu[i * prime[j]] = -mu[i];
}
}
for (int i = 1; i <= tot; i++) {
for (int j = 1; j * prime[i] <= MAXN - 5; j++) {
f[j * prime[i]] += mu[j];
}
}
for (int i = 1; i <= MAXN - 5; i++) fsum[i] = fsum[i - 1] + f[i];
}
inline ll read() {
ll x = 0;
bool f = true;
char c = getchar();
while (!isdigit(c)) {
if (c == '-') f = false;
c = getchar();
}
while (isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return f ? x : -x;
}
inline void write(ll x, bool f = 0) {
ll tp2 = 0;
char Nu[64];
if (x<0) x = -x, putchar('-');
if (x==0) putchar('0');
else {
while (x) {
Nu[++tp2] = x % 10 + '0', x /= 10;
}
while (tp2) putchar(Nu[tp2--]);
}
if (f) putchar('\n');
else putchar(' ');
return;
}
int main() {
Linear_Sieve();
cin >> t;
while (t--) {
n = read();
m = read();
ll ans = 0;
if (n > m) swap(n, m);
for (int l = 1, r; l <= n; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (fsum[r] - fsum[l - 1]) * (n / l) * (m / l);
}
write(ans, true);
}
return 0;
}
杜教筛
类比线性筛、埃氏筛能筛质数与积性函数值,杜教筛是一种用于大范围筛数论函数前缀和的工具,它的底层思想是构造卷积与 \(\text{Möbius}\) 反演的运用。
假设现在需要求 \(f\) 的前缀和,记 \(\displaystyle\sum_{i=1}^n f(i)=S(n)\),那么考虑:
推出杜教筛的核心式子:
理论上,只要找到一个合适的积性函数 \(g\) 去计算 \(g\) 与 \(f*g\) 的前缀和,那么便可以计算任一数论函数的前缀和。
代码如下:
ll GetSum(int n) { // 算 f 前缀和的函数
ll ans = ...; // f * g 的前缀和
for(ll l = 2, r; l <= n; l = r + 1) {
r = (n / (n / l));
ans -= (g_sum(r) - g_sum(l - 1)) * GetSum(n / l);
// g_sum 是 g 的前缀和
// 递归 GetSum 求解
} return ans;
}
计算 \(\varphi\)
考虑 \(\varphi*\mathbb{1}=\text{id}\),那么 \(f=\varphi,g=\mathbb{1}\),那么 \(f*g\) 的前缀和即 \(\text{id}\) 的前缀和就是 \(\displaystyle\frac{n(n+1)}{2}\)。
计算 \(\mu\)
考虑 \(\mu*\mathbb{1}=\varepsilon\),那么 \(f=\mu,g=\mathbb{1}\),那么 \(f*g\) 的前缀和即 \(\varepsilon\) 的前缀和就是 \(1\)。
朴素的杜教筛的时间复杂度是 \(O(n^{\frac{3}{4}})\)。可以先用线性筛筛出 \(m\) 个前缀和并用 unordered_map 存下来,当 \(m=n^{\frac{2}{3}}\) 时杜教筛时间复杂度取最小值,为 \(O(n^{\frac{2}{3}})\)。
原根与离散对数
阶
满足 \(a^n\equiv1\pmod{m}\) 的 \(n\) 称为 \(a\) 模 \(m\) 的阶,记作 \(\delta_m(a)\)。
\(\textbf{性质}\ \textbf1\)
\(a,a^2,\cdots,a^{\delta_{m}(a)}\) 模 \(m\) 两两互不同余。
\(\textbf{证明}\ \textbf1\)
若存在 \(1\le i < j < \delta_m(a)\),使得\(a^i\equiv a^j\pmod m\),则 \(a^{|i-j|}\equiv1\pmod m\),显然 \(0<|i-j|<\delta_m(a)\),与阶的最小性相矛盾,故原命题成立。
\(\textbf{性质}\ \textbf2\)
若 \(a^n\equiv 1\pmod m\),则 \(\delta_m(a)\ |\ n\)。
\(\textbf{证明}\ \textbf2\)
设 \(n=\delta_m(a)q+r,0\le r<\delta_m(a)\)。
若 \(r\ne 0\),则
与阶的最小性相矛盾。
若 \(r = 0\),则 \(\delta_m(a)\ |\ n\),故原命题成立。
据此还能推出:若 \(a^p\equiv a^q\pmod m\),则 \(p\equiv q\pmod m\),\(\delta_m(a)\ |\ \varphi(m)\)。
求阶
由于 \(\delta_m(a)\ |\ \varphi(m)\),所以求阶只需要尝试把所有 \(\varphi(m)\) 的所有因子除去便能求出 \(\delta_m(a)\),这就是试除法。
试除法的步骤是:
-
设 \(d=\frac{\varphi(m)}{p_x}\),其中 \(p_x\) 表示已除去的所有因子的积。
-
在试除的过程中,若 \(a^d\equiv1\pmod m\) 不成立,则该因子不能除去,否则可以除去。
原根
设 \(m\in\mathbb{N}^*,g\in\mathbb{Z}\),若 \(m\perp g,\delta_m(g)=\varphi(m)\),则称 \(g\) 为模 \(m\) 的一个原根。
原根判定定理
设 \(m \ge 3,m\perp g\),则 \(g\) 是模 \(m\) 的一个原根的充要条件是:对于 \(m\) 的每个素因子 \(p\),都有 \(g^{\frac{\varphi(m)}{p}}\equiv\hspace{-3.3mm}/\ \ 1\pmod m\)。
证明见 OI-wiki。
原根个数
若 \(m\) 存在原根,则原根个数为 \(\varphi(\varphi(m))\)。
原根存在性定理
一个数 \(m\) 存在原根当且仅当 \(m=2,4,p^\alpha,p^{2\alpha};p\ \small\textrm{是奇素数,}\alpha\in\mathbb{N}^*\)。
离散对数
离散对数的定义与对数类似。
设 \(m\) 有原根,它的一个原根为 \(g\)。对一个 \(a\) 使 \(a\perp m\),必定存在唯一的 \(k(0\le k <\varphi(m))\),使得 \(g^k\equiv a\pmod m\),则称 \(k\) 为以 \(g\) 为底,模 \(m\) 的离散对数,记作 \(k=\text{ind}_ga\)。

浙公网安备 33010602011771号