数论 $\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(x)=\sum_{d|x}f(d)g(\frac{x}{d})=\sum_{ab=x}f(a)g(b) \]

记为 \(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\) 也是积性函数。

常见卷积

\[\varepsilon=\mu*\mathbb{1} \]

\[d=\mathbb{1}*\mathbb{1} \]

\[\sigma=\text{id}*\mathbb{1} \]

\[\varphi=\mu*\text{id} \]

此类卷积会在后面的莫比乌斯反演中大量运用。

\(\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(n)=\sum_{d|n}g(d) \]

则称 \(f\)\(g\)\(\text{Möbius}\) 变换,\(g\)\(f\)\(\text{Möbius}\) 反演。

这里容易看出,\(f=g*\mathbb{1}\)

\(\text{Möbius}\) 反演的常见形式是 \(f=\varepsilon,g=\mu\) 的情况。

\(\text{Examples:}\)

P2398 GCD SUM

\[\sum_{i=1}^{n}\sum_{j=1}^{n}\gcd(i,j) \]

考虑对式子作下列变换:

\[\begin{array}{ll} \displaystyle\sum_{i=1}^{n}\sum_{j=1}^{n}\gcd(i,j) &=& \displaystyle\sum_{k=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)=k] \\ &=& \displaystyle\sum_{k=1}^{n}\sum_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{n}{k}\right\rfloor}[\gcd(i,j)=1] \\ &=& \displaystyle\sum_{k=1}^{n}\sum_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{d|\gcd(i,j)}\mu(d) \\ &=& \displaystyle\sum_{k=1}^{n}\sum_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{d=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\mu(d)[d|i][d|j] \\ &=& \displaystyle\sum_{k=1}^{n}\sum_{d=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\mu(d)\sum_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}[d|i]\sum_{j=1}^{\left\lfloor\frac{n}{k}\right\rfloor}[d|j]\\ &=& \displaystyle\sum_{k=1}^{n}\sum_{d=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\mu(d)\left\lfloor\frac{n}{kd}\right\rfloor\left\lfloor\frac{n}{kd}\right\rfloor \end{array} \]

第一行,枚举 \(\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}\) 反演板子题:

P2257 YY 的 GCD

\[\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=p],p\in \text{prime} \]

比刚刚那题一目了然,但刚刚用 \(\varphi\)\(O(Tn\sqrt n)\) 的做法无法通过,只能用反演做法。

化简得到:

\[\displaystyle\sum_{p=1}^{\min(n,m)}\sum_{d=1}^{\min(\left\lfloor\frac{n}{p}\right\rfloor,\left\lfloor\frac{m}{p}\right\rfloor)}\mu(d)\left\lfloor\frac{n}{pd}\right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor,p\in \text{prime} \]

此时不能再枚举 \(p\),因为枚举 \(p\) 的时间复杂度还是 \(O(Tn\sqrt n)\) 的。

考虑设 \(C=pd,p\in\text{prime}\),再枚举 \(C\),则原式化为:

\[\sum_{C=1}^{\min(n,m)}\left\lfloor\frac{n}{C}\right\rfloor\left\lfloor\frac{m}{C}\right\rfloor\sum_{p|C,p\in\text{prime}}\mu(\frac{C}{p}) \]

预处理后一部分,整除分块即可,时间复杂度 \(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)\),那么考虑:

\[\begin{array}{ll} && \displaystyle\sum_{i=1}^n (f*g)(i) \\ &=& \displaystyle\sum_{i=1}^n\sum_{d|i}f(d)g(\frac{i}{d}) \\ &=& \displaystyle\sum_{d=1}^ng(d)S(\left\lfloor\frac{n}{d}\right\rfloor) \end{array} \]

推出杜教筛的核心式子:

\[g(1)S(n)=\sum_{i=1}^n (f*g)(i)-\sum_{i=2}^ng(i)S(\left\lfloor\frac{n}{i}\right\rfloor) \]

理论上,只要找到一个合适的积性函数 \(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\),则

\[a^r\equiv a^r(a^{\delta_m(a)})^q\equiv a^n \equiv1\pmod m \]

与阶的最小性相矛盾。

\(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)\),这就是试除法。

试除法的步骤是:

  1. \(d=\frac{\varphi(m)}{p_x}\),其中 \(p_x\) 表示已除去的所有因子的积。

  2. 在试除的过程中,若 \(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\)

posted @ 2024-07-05 16:23  Cuset_VoidAldehyde  阅读(61)  评论(0)    收藏  举报