数论专题笔记

· · 个人记录

1 数论中的基础知识

1.1 整除

1.1.1 定义

a,b 是整数,如果存在一个整数 c,使得 b=ac,则称 a 整除 b(或 ba 整除),记作 a\mid b

1.1.2 定理

  1. (反射性)对于所有整数 a,满足 a \mid a
  2. (传递性)若 a \mid bb \mid c,则 a \mid c
  3. a,b_1,b_2,\cdots,b_n 都是整数,且 a \mid b_i1 \le i \le n),则 a \mid b_1c_1+b_2c_2+\cdots+b_nc_n\forall c_1,c_2,\cdots,c_n \in \mathbb{Z})。
  4. a,b_1,b_2,\cdots,b_n 都是整数,且 a \mid b_i1 \le i \le n),则 a \mid b_1c_1 \times b_2c_2 \times \cdots \times b_nc_n\forall c_1,c_2,\cdots,c_n \in \mathbb{Z})。
  5. a \mid ba \mid b \pm c,则 a \mid c
  6. 若整数 a,b,c,d,e 满足 a \mid b-ca \mid d-e,则 a \mid bd - ce
  7. a\mid b,则 \forall c \in \mathbb{Z}ac\mid bc;若 ac \mid bcc \ne 0,则 a\mid b

1.1.3 证明

定理 1、2、7 可直接由定义推导,定理 3-6 通过将 b_i 表示为 a \times w_iw_i 为整数),代入等式后化简可证。

1.2 同余

1.2.1 定义

a,b,n 是整数,若 n \mid a-b,则称 abn 同余,记作 a \equiv b \pmod {n}

1.2.2 定理

  1. (反射性)a \equiv a \pmod n
  2. (对称性)若 a \equiv b \pmod n,则 b \equiv a \pmod n
  3. (传递性)若 a \equiv b \pmod nb \equiv c \pmod n,则 a \equiv c \pmod n
  4. a \equiv c \pmod nb \equiv d \pmod n,则 a+b \equiv c+d \pmod nab \equiv cd \pmod n
  5. a \equiv b \pmod n,则 ac \equiv bc \pmod {nc};若 ac \equiv bc \pmod {nc}c \ne 0,则 a \equiv b \pmod n

1.2.3 证明

定理 1、2 由定义直接成立;定理 3-5 利用整除性质推导,例如定理 3 可通过 n \mid (a-b)+(b-c) = a-c 证明。

1.3 数论函数

定义域为正整数、值域为复数集子集的函数称为数论函数。

1.3.1 积性函数

1.3.2 加性函数

1.4 模运算

带余除法:\forall a,b>0,存在唯一整数 q,r 满足 a=bq+r0 \le r <b),r 记为 a \bmod b

运算法则:

  1. (a+b) \bmod M = (a \bmod M + b \bmod M) \bmod M
  2. (a-b) \bmod M = (a \bmod M - b \bmod M) \bmod M
  3. (a \times b) \bmod M = (a \bmod M \times b \bmod M) \bmod M

注意:除法无直接模运算法则,需通过逆元转换。

2 素数

2.1 唯一分解定理

每个大于 1 的整数都能唯一表示为质因数之积:n=\prod p_i^{a_i}p_i 为素数,p_1<p_2<\cdotsa_i \ge 1)。

推论:n 中最多含有一个大于 \sqrt{n} 的因子。

分解代码:

void decompose(int x){
    for(int i=2;i*i<=x;++i)
        while(x%i==0) ++a[i],x/=i;
    if(x) ++a[x];
}
int main(){
    int n;scanf("%d",&n);
    decompose(n);
    for(int i=1;i<=n;++i) 
        if(a[i]) printf("%d %d\n",a[i],i);
}

2.2 费马小定理若

证明:$\{1,2,\cdots,p-1\}$ 中每个数乘 $a$ 模 $p$ 互不相同,故 $\prod_{i=1}^{p-1} i \equiv a^{p-1} \prod_{i=1}^{p-1}i \pmod p$,约去乘积项得证。 ### 2.3 素数筛 #### 2.3.1 普通筛 ($O(n \log n)$) ```cpp for(int i=2;i<=n;++i){ if(!vis[i]) prime[++tot]=i; for(int j=2;j*i<=n;++j) vis[j*i]=1; } ``` #### 2.3.2 埃氏筛($O(n \log \log n)$) ``` cpp for(int i=2;i<=n;++i){ if(!vis[i]){ prime[++tot]=i; for(int j=2;j*i<=n;++j) vis[i*j]=1; } } ``` #### 2.3.3 线性筛($O(n)$) ```cpp 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; // 保证每个数被最小质因子筛去 } } ``` #### 2.3.4 线性筛求积性函数(以 $d(n)$ 为例) ```cpp d[1]=d[0]=1; for(int i=2;i<=n;++i){ if(!vis[i]){ prime[++tot]=i; P[i]=i,A[i]=1; d[i]=2; // 素数的因子个数为2 } else { if(P[i]!=P[i/P[i]]) A[i]=1; else A[i]=A[i/P[i]]+1; d[i]=(A[i]+1)*d[i/pow(P[i],A[i])]; } for(int j=1;j<=tot&&i*prime[j]<=n;++j){ vis[i*prime[j]]=1; P[i*prime[j]]=prime[j]; if(i%prime[j]==0) break; } } ``` ## 3 欧拉函数与欧拉定理 ### 3.1 欧拉函数 $\varphi(n)$ 表示 $1\sim n$ 中与 $n$ 互质的数的个数,是积性函数。 #### 3.1.1 单个欧拉函数求解($O(\sqrt{n})$) ```cpp int tphi(int n) { int ans=n; for(int i=2;i*i<=n;++i) if(n%i==0){ ans=ans/i*(i-1); // 乘 (1-1/i) while(n%i==0) n/=i; } if(n!=1) ans=ans/n*(n-1); return ans; } ``` #### 3.1.2 线性筛求欧拉函数 ```cpp void sol(int n){ phi[1]=1; for(int i=2;i<=n;++i){ if(!phi[i]) phi[i]=i-1,prime[++tot]=i; // 素数的欧拉函数为i-1 for(int j=1;j<=tot&&i*prime[j]<=n;++j){ if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; // 最小质因子多次出现 break; } else { phi[i*prime[j]]=phi[i]*(prime[j]-1); // 最小质因子首次出现 } } } } ``` #### 3.1.3 核心性质 $n = \sum_{d|n} \varphi(d)$(将 $1\sim n$ 按与 $n$ 的 $\gcd$ 分组推导)。 ### 3.2 欧拉定理 设 $a,n \in \mathbb{N}_+$,若 $\gcd(a,n)=1$,则 $a^{\varphi(n)} \equiv 1 \pmod n$。 证明:$\{x_1,x_2,\cdots,x_{\varphi(n)}\}$(与 $n$ 互质的数)乘 $a$ 模 $n$ 仍为该集合,乘积相等约去后得证。 ### 3.3 扩展欧拉定理 设 $a,n \in \mathbb{N}_+$,则 $a^{2\varphi(n)} \equiv a^{\varphi(n)} \pmod n$; 若 $k \ge \varphi(n)$,则 $a^k \equiv a^{k \bmod \varphi(n) + \varphi(n)} \pmod n$。 ## 4 二元线性不定方程 ### 4.1 裴蜀定理 若 $a$,$b$ 不全为 $0$,则 $\gcd(a,b) \mid ax+by$($\forall x,y \in \mathbb{Z}$),且存在 $x,y \in \mathbb{Z}$ 使得 $ax+by=\gcd(a,b)$。 证明:设 $S$ 为 $ax+by$ 的所有取值,$d$ 为 $S$ 中最小正整数,可证 $d$ 是 $\gcd(a,b)$。 ### 4.2 扩展欧几里得(exgcd) #### 4.2.1 求特解 ```cpp void exgcd(int a,int b,int &x,int &y){ if(b==0){ x=1; y=0; return ; } exgcd(b,a%b,x,y); int tx=x; x=y; y=tx-a/b*y; } ``` 注意:方程 $ax+by=c$ 有解当且仅当 $\gcd(a,b) \mid c$,特解需乘 $c/\gcd(a,b)$。 #### 4.2.2 求通解 设特解为 $(x_0,y_0)$,则通解为:$(x_0 + k \cdot \frac{b}{\gcd(a,b)}, \quad y_0 - k \cdot \frac{a}{\gcd(a,b)}) \quad (k \in \mathbb{Z})

5 模意义下的乘法逆元

5.1 定义

若 ax \equiv 1 \pmod p,则 x 为 a 在模 p 下的逆元,记为 a^{-1} \pmod p

5.2 逆元求法

5.2.1 扩展欧几里得求逆元

将 ax \equiv 1 \pmod p 转化为 ax + py = 1,调用 exgcd 求解 x(要求 \gcd(a,p)=1)。

5.2.2 费马小定理求逆元

### 5.3 核心作用将除法模运算转化为乘法: $\frac{a}{b} \mod p = a \times b^{-1} \mod p$。 ### 5.4 威尔逊定理 $(p-1)! \equiv -1 \pmod p$ 的充要条件是 $p$ 为素数。 ## 6 线性同余方程组 ### 6.1 中国剩余定理(CRT) 适用于 $m_i$ 两两互质的方程组: $$\begin{cases}x\equiv a_1 \pmod {m_1} \\x\equiv a_2 \pmod {m_2} \\\vdots \\x\equiv a_n \pmod {m_n}\end{cases}$$ 令 $M=\prod m_i$,$M_i=M/m_i$,$M_i^{-1}$ 为 $M_i$ 模 $m_i$ 的逆元,则解为 $x=\sum a_i M_i M_i^{-1} \pmod M$。 ### 6.2 扩展中国剩余定理(exCRT) 适用于任意 $m_i$,核心是两两合并方程:合并 $\begin{cases}x \equiv a_1 \pmod {m_1} \\x \equiv a_2 \pmod {m_2}\end{cases}$,转化为 $k_1m_1 - k_2m_2 = a_2 - a_1$,用 exgcd 求 $k_1$。合并后方程为 $x \equiv x_0 \pmod {\text{lcm}(m_1,m_2)}$($x_0$ 为特解)。 核心代码: ```cpp signed main(){ int n,a1,b1,a2,b2; scanf("%lld%lld%lld",&n,&a1,&b1); for(int i=1;i<n;++i){ scanf("%lld%lld",&a2,&b2); int k1,k2; int d=exgcd(a1,a2,k1,k2); int bg=a2/d; if((b2-b1)%d!=0) return !printf("Impossible\n"); k1=(mul(k1,(b2-b1)/d,bg)); // 龟速乘避免溢出 b1=k1*a1+b1; a1=a1*bg; b1=(b1%a1+a1)%a1; } printf("%lld\n",b1); } ``` ## 7 组合数学与计数 ### 7.1 二项式定理 $$(x+y)^n = \sum_{i=0}^n C_{n}^{i} x^i y^{n-i}$$ 用数学归纳法结合组合数性质 $C_k^{i-1}+C_k^i=C_{k+1}^i$ 证明。 ### 7.2 卢卡斯定理(Lucas 定理) 若 $p$ 为素数,则 $C_n^m \equiv C_{\lfloor n/p \rfloor}^{\lfloor m/p \rfloor} \times C_{n \bmod p}^{m \bmod p} \pmod p$。 证明:利用二项式定理和引理 $(x+y)^p \equiv x^p + y^p \pmod p$,对比 $x^m$ 系数得证。 求解组合数时,结合费马小定理:$C_n^m \equiv n! \times (m!)^{p-2} \times ((n-m)!)^{p-2} \pmod p$。 ## 8 高级数论算法 ### 8.1 数论函数进阶 #### 8.1.1 狄利克雷卷积 定义:$(f*g)(x) = \sum_{k|x} f(k)g(x/k)$,满足交换律和结合律。 - 单位元:$\varepsilon * f = f

8.1.2 莫比乌斯函数

-1, & \text{无平方因子且质因子个数为奇数} \\ 0, & \text{有平方因子} \\ 1, & \text{无平方因子且质因子个数为偶数} \end{cases}

8.2 莫比乌斯反演

8.3 整除分块

用于快速计算 \sum_{i=1}^n \lfloor n/i \rfloor 类求和,时间复杂度 O(\sqrt{n})

for (int l = 1, r; l <= n; l = r + 1)
    r = n / (n / l),
    ans += (r - l + 1) * (n / r);

8.4 杜教筛

快速求积性函数前缀和,核心公式:

G(n) = \sum_{i=1}^n h(i) - \sum_{i=2}^n f(i)G(\lfloor n/i \rfloor)

(其中 f \times g=hG 为 g 的前缀和)模板代码(求 \mu(x) 前缀和):

const int N = 5e6 + 5;
int miu[N], p[N];
bool is_p[N];
map <int, int> mp;

void sieve(int N) {
    miu[1] = 1;
    for (int i = 2; i <= N; i++) {
        if (!is_p[i]) p[++c] = i, miu[i] = -1;
        for (int j = 1; j <= c && i * p[j] <= N; j++) {
            is_p[i * p[j]] = 1;
            if (i % p[j] == 0) { miu[i * p[j]] = 0; break; }
            miu[i * p[j]] = -miu[i];
        }
    }
    for (int i = 2; i <= N; i++) miu[i] += miu[i - 1];
}

int cal_miu(int x) {
    if (x <= 5e6) return miu[x];
    if (mp.count(x)) return mp[x];
    int res = 1;
    for (int l = 2, r; l <= x; l = r + 1)
        r = x / (x / l),
        res -= (r - l + 1) * cal_miu(x / r);
    return mp[x] = res;
}

8.5 Powerful Number 筛(PN 筛)

适用于杜教筛无法解决的函数,核心是利用“幂数”(所有质因子次数 \ge 2)的稀疏性(n 以内幂数个数为 O(\sqrt{n}))。

模板代码(Min_25 筛替代):

const int mod = 1e9 + 7;
const int inv2 = 500000004;
const int inv6 = 166666668;
const int N = 5e6 + 5;
int p[1000000], phi[N], c;
bool is_p[N];

void sieve(int N) {
    phi[1] = 1;
    for (int i = 2; i <= N; i++) {
        if (!is_p[i]) p[++c] = i, phi[i] = i - 1;
        for (int j = 1; j <= c && i * p[j] <= N; j++) {
            is_p[i * p[j]] = 1;
            if (i % p[j] == 0) { phi[i * p[j]] = phi[i] * p[j]; break; }
            phi[i * p[j]] = phi[i] * (p[j] - 1);
        }
    }
    for (int i = 2; i <= N; i++) (phi[i] *= i) %= mod;
    for (int i = 2; i <= N; i++) (phi[i] += phi[i - 1]) %= mod;
}

int mp[N], n, ans;
int cal_G(int x) {
    if (x <= 5e6) return phi[x];
    if (mp[n / x]) return mp[n / x];
    int X = x % mod;
    int res = X * (X + 1) % mod * (2 * X + 1) % mod * inv6 % mod;
    for (int l = 2, r; l <= x; l = r + 1)
        r = x / (x / l),
        res -= (l + r) % mod * (r - l + 1) % mod * inv2 % mod * cal_G(x / r);
    return mp[n / x] = res;
}

void dfs(int nw, int num, int H) {
    if (nw > c || num * p[nw] > n) {
        (ans += H * cal_G(n / num)) %= mod;
        return;
    }
    dfs(nw + 1, num, H);
    for (int mu = p[nw] * p[nw], s = 1; num * mu <= n; mu *= p[nw], s++)
        dfs(nw + 1, num * mu, s * (p[nw] - 1) % mod * mu % mod * H % mod);
}

signed main() {
    scanf("%lld", &n), sieve(5e6), dfs(1, 1, 1);
    printf("%lld", ans);
}