Part05 数学与其他
数学与其他
初等数论
5. 同余式
如果整数 aaa 和 bbb 除以正整数 mmm 的余数相同,则称 aaa 和 bbb 模 mmm 同余,记作:
a≡b(modm)a \equiv b \pmod{m} a≡b(modm)
模板代码(同余式基本运算):
// 判断a和b是否模m同余
bool isCongruent(int a, int b, int m) {return (a % m) == (b % m);
}// 模m加法:(a + b) mod m
int modAdd(int a, int b, int m) {return (a % m + b % m) % m;
}// 模m减法:(a - b) mod m
int modSub(int a, int b, int m) {return (a % m - b % m + m) % m;
}// 模m乘法:(a * b) mod m
int modMul(int a, int b, int m) {return (1LL * a * b) % m;
}
7. 欧拉函数和欧拉定理
欧拉函数
欧拉函数 ϕ(n)\phi(n)ϕ(n) 表示小于等于 nnn 的正整数中与 nnn 互质的数的个数。
若 nnn 有质因数分解 n=p1k1p2k2⋯prkrn = p_1^{k_1} p_2^{k_2} \cdots p_r^{k_r}n=p1k1p2k2⋯prkr,则:
ϕ(n)=n∏i=1r(1−1pi)\phi(n) = n \prod_{i=1}^r \left(1 - \frac{1}{p_i}\right) ϕ(n)=ni=1∏r(1−pi1)
欧拉定理
若 aaa 和 nnn 互质(即 gcd(a,n)=1\gcd(a, n) = 1gcd(a,n)=1),则:
aϕ(n)≡1(modn)a^{\phi(n)} \equiv 1 \pmod{n} aϕ(n)≡1(modn)
模板代码(欧拉函数和欧拉定理):
// 计算欧拉函数φ(n)
int eulerPhi(int n) {int result = n;for (int p = 2; p * p <= n; p++) {if (n % p == 0) {while (n % p == 0)n /= p;result -= result / p;}}if (n > 1)result -= result / n;return result;
}// 使用欧拉定理计算a^b mod m (当gcd(a, m) = 1)
int powModEuler(int a, int b, int m) {int phi = eulerPhi(m);b = b % phi;int result = 1;while (b > 0) {if (b & 1)result = (1LL * result * a) % m;a = (1LL * a * a) % m;b >>= 1;}return result;
}
7. 费马小定理
若 ppp 为质数,且 aaa 不是 ppp 的倍数(即 gcd(a,p)=1\gcd(a, p) = 1gcd(a,p)=1),则:
ap−1≡1(modp)a^{p-1} \equiv 1 \pmod{p} ap−1≡1(modp)
模板代码(费马小定理):
// 使用费马小定理计算a^b mod p (p为质数)
int powModFermat(int a, int b, int p) {// 根据费马小定理,a^(p-1) ≡ 1 mod pb = b % (p - 1);int result = 1;while (b > 0) {if (b & 1)result = (1LL * result * a) % p;a = (1LL * a * a) % p;b >>= 1;}return result;
}
7. 威尔逊定理
ppp 是质数的充分必要条件是:
(p−1)!≡−1(modp)(p-1)! \equiv -1 \pmod{p} (p−1)!≡−1(modp)
模板代码(威尔逊定理判断质数):
// 使用威尔逊定理判断n是否为质数
bool isPrimeWilson(int n) {if (n <= 1) return false;if (n == 2) return true;long long fact = 1;for (int i = 2; i < n; i++) {fact = (fact * i) % n;}return (fact + 1) % n == 0;
}
7. 裴蜀定理
对于任意整数 aaa 和 bbb,存在整数 xxx 和 yyy 使得:
ax+by=gcd(a,b)ax + by = \gcd(a, b) ax+by=gcd(a,b)
模板代码(裴蜀定理):
// 扩展欧几里得算法,求解ax + by = gcd(a, b)
int extendedGcd(int a, int b, int &x, int &y) {if (b == 0) {x = 1;y = 0;return a;}int x1, y1;int gcd = extendedGcd(b, a % b, x1, y1);x = y1;y = x1 - (a / b) * y1;return gcd;
}// 检查ax + by = c是否有整数解
bool hasSolution(int a, int b, int c) {int x, y;int gcd = extendedGcd(a, b, x, y);return c % gcd == 0;
}
7. 模运算意义下的逆元
若 aaa 和 mmm 互质,则存在整数 bbb 使得:
a⋅b≡1(modm)a \cdot b \equiv 1 \pmod{m} a⋅b≡1(modm)
模板代码(求逆元):
// 使用扩展欧几里得算法求逆元
int modInverseExtended(int a, int m) {int x, y;int gcd = extendedGcd(a, m, x, y);if (gcd != 1) {// 逆元不存在return -1;}return (x % m + m) % m;
}// 使用费马小定理求逆元(m为质数)
int modInverseFermat(int a, int m) {return powModFermat(a, m - 2, m);
}
7. 扩展欧几里得算法
用于求解裴蜀等式 ax+by=gcd(a,b)ax + by = \gcd(a, b)ax+by=gcd(a,b) 的整数解 xxx 和 yyy。
模板代码(扩展欧几里得算法):
// 扩展欧几里得算法
int extendedGcd(int a, int b, int &x, int &y) {if (b == 0) {x = 1;y = 0;return a;}int x1, y1;int gcd = extendedGcd(b, a % b, x1, y1);x = y1;y = x1 - (a / b) * y1;return gcd;
}
7. 中国剩余定理
若 m1,m2,…,mkm_1, m_2, \ldots, m_km1,m2,…,mk 两两互质,则同余方程组:
{x≡a1(modm1)x≡a2(modm2)⋮x≡ak(modmk)\begin{cases} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \vdots \\ x \equiv a_k \pmod{m_k} \end{cases} ⎩⎨⎧x≡a1(modm1)x≡a2(modm2)⋮x≡ak(modmk)
有唯一解模 M=m1m2⋯mkM = m_1 m_2 \cdots m_kM=m1m2⋯mk。
模板代码(中国剩余定理):
- 计算所有的模数 MMM;
- 计算第 iii 个方程的 ci=Mmic_i=\frac{M}{m_i}ci=miM ;
- 计算 cic_ici 在模 mim_imi 意义下的逆元 ci−1c_i^{-1}ci−1;
- x=∑i=1nricici−1x=\sum_{i=1}^{n} r_i c_i c_i^{-1}x=∑i=1nricici−1;
// 中国剩余定理求解同余方程组
int chineseRemainderTheorem(const vector<int>& a, const vector<int>& m) {int n = a.size();int M = 1;for (int i = 0; i < n; i++) {M *= m[i];}int result = 0;for (int i = 0; i < n; i++) {int Mi = M / m[i];int inv = modInverseExtended(Mi, m[i]);result = (result + 1LL * a[i] * Mi % M * inv % M) % M;}return result;
}
离散与组合数学
6. 多重集合
多重集合(Multiset)是允许元素重复出现的集合。
记法:M={a1m1,a2m2,…,akmk}M = \{a_1^{m_1}, a_2^{m_2}, \ldots, a_k^{m_k}\}M={a1m1,a2m2,…,akmk},其中 mim_imi 表示元素 aia_iai 的重数。
6. 等价类
等价类是在等价关系下具有相同性质的元素的集合。
若 RRR 是集合 AAA 上的等价关系,则对于 a∈Aa \in Aa∈A,其等价类为:
[a]={x∈A∣xRa}[a] = \{x \in A \mid x R a\} [a]={x∈A∣xRa}
6. 多重集上的排列
对于多重集 M={a1m1,a2m2,…,akmk}M = \{a_1^{m_1}, a_2^{m_2}, \ldots, a_k^{m_k}\}M={a1m1,a2m2,…,akmk},其全排列数为:
n!m1!m2!⋯mk!其中n=∑i=1kmi\frac{n!}{m_1! m_2! \cdots m_k!} \quad \text{其中} \quad n = \sum_{i=1}^k m_i m1!m2!⋯mk!n!其中n=i=1∑kmi
6. 多重集上的组合
从多重集 M={a1m1,a2m2,…,akmk}M = \{a_1^{m_1}, a_2^{m_2}, \ldots, a_k^{m_k}\}M={a1m1,a2m2,…,akmk} 中选取 rrr 个元素的组合数,当 r≤mir \leq m_ir≤mi 时为:
(k+r−1r)\binom{k + r - 1}{r} (rk+r−1)
6. 错排列、圆排列
错排列(Derangement)
错排列是指没有元素出现在其原始位置的排列。
nnn 个元素的错排列数 DnD_nDn 满足:
Dn=(n−1)(Dn−1+Dn−2)其中D1=0,D2=1D_n = (n-1)(D_{n-1} + D_{n-2}) \quad \text{其中} \quad D_1 = 0, D_2 = 1 Dn=(n−1)(Dn−1+Dn−2)其中D1=0,D2=1
通项公式:
Dn=n!∑k=0n(−1)kk!D_n = n! \sum_{k=0}^n \frac{(-1)^k}{k!} Dn=n!k=0∑nk!(−1)k
圆排列(Circular Permutation)
nnn 个元素的圆排列数为:
(n−1)!(n-1)! (n−1)!
6. 鸽巢原理
鸽巢原理(Pigeonhole Principle):
如果将 n+1n+1n+1 个物体放入 nnn 个盒子中,那么至少有一个盒子包含至少两个物体。
推广形式:
如果将 kn+1kn+1kn+1 个物体放入 nnn 个盒子中,那么至少有一个盒子包含至少 k+1k+1k+1 个物体。
6. 二项式定理
二项式定理:
(x+y)n=∑k=0n(nk)xn−kyk(x + y)^n = \sum_{k=0}^n \binom{n}{k} x^{n-k} y^k (x+y)n=k=0∑n(kn)xn−kyk
其中 (nk)=n!k!(n−k)!\binom{n}{k} = \frac{n!}{k!(n-k)!}(kn)=k!(n−k)!n! 是二项式系数。
7. 容斥原理
容斥原理(Inclusion-Exclusion Principle):
对于有限集 A1,A2,…,AnA_1, A_2, \ldots, A_nA1,A2,…,An,有:
$$
\left| \bigcup_{i=1}^n A_i \right| = \sum_{i=1}^n |A_i| \
- \sum_{1 \leq i < j \leq n} |A_i \cap A_j| \
- \sum_{1 \leq i < j < k \leq n} |A_i \cap A_j \cap A_k| \
- \cdots + (-1)^{n+1} |A_1 \cap A_2 \cap \cdots \cap A_n|
$$
7. 卡特兰(Catalan)数
卡特兰数 CnC_nCn 的计算公式:
Cn=1n+1(2nn)=(2n)!(n+1)!n!C_n = \frac{1}{n+1} \binom{2n}{n} = \frac{(2n)!}{(n+1)!n!} Cn=n+11(n2n)=(n+1)!n!(2n)!
递推关系:
C0=1,Cn+1=∑i=0nCiCn−iC_0 = 1, \quad C_{n+1} = \sum_{i=0}^n C_i C_{n-i} C0=1,Cn+1=i=0∑nCiCn−i
应用场景:
- 合法的括号序列数量
- 二叉树的形态数量
模板代码(计算卡特兰数):
#include <iostream>
#include <vector>
using namespace std;// 计算卡特兰数(使用动态规划)
long long catalanNumber(int n) {vector<long long> dp(n + 1, 0);dp[0] = 1;for (int i = 1; i <= n; i++) {for (int j = 0; j < i; j++) {dp[i] += dp[j] * dp[i - j - 1];}}return dp[n];
}// 使用公式直接计算(注意可能溢出)
long long catalanFormula(int n) {long long result = 1;for (int i = 1; i <= n; i++) {result = result * (4 * i - 2) / (i + 1);}return result;
}int main() {int n;cin >> n;cout << "Catalan number C_" << n << " = " << catalanNumber(n) << endl;return 0;
}
模板代码(计算错排列数):
#include <iostream>
#include <vector>
using namespace std;// 计算错排列数
long long derangement(int n) {if (n == 0) return 1;if (n == 1) return 0;vector<long long> dp(n + 1);dp[0] = 1;dp[1] = 0;for (int i = 2; i <= n; i++) {dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]);}return dp[n];
}int main() {int n;cin >> n;cout << "Derangement number D_" << n << " = " << derangement(n) << endl;return 0;
}
模板代码(计算多重集排列数):
#include <iostream>
#include <vector>
using namespace std;// 计算阶乘
long long factorial(int n) {long long result = 1;for (int i = 2; i <= n; i++) {result *= i;}return result;
}// 计算多重集排列数
long long multisetPermutation(const vector<int>& multiplicities) {int total = 0;for (int m : multiplicities) {total += m;}long long numerator = factorial(total);long long denominator = 1;for (int m : multiplicities) {denominator *= factorial(m);}return numerator / denominator;
}int main() {vector<int> multiset = {2, 3, 1}; // 表示有3种元素,重数分别为2,3,1cout << "Multiset permutation count: " << multisetPermutation(multiset) << endl;return 0;
}
线性代数
5. 向量与矩阵的概念
向量
向量是一个有序数组,可以表示为一列数(列向量)或一行数(行向量)。
在数学中,一个 nnn 维列向量表示为:
v=(v1v2⋮vn)\mathbf{v} = \begin{pmatrix} v_1 \\ v_2 \\ \vdots \\ v_n \end{pmatrix} v=v1v2⋮vn
矩阵
矩阵是一个二维数组,由行和列组成。一个 m×nm \times nm×n 的矩阵表示为:
A=(a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn)A = \begin{pmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{pmatrix} A=a11a21⋮am1a12a22⋮am2⋯⋯⋱⋯a1na2n⋮amn
6. 向量的运算
向量加法
两个相同维度的向量 u\mathbf{u}u 和 v\mathbf{v}v 可以相加:
u+v=(u1+v1u2+v2⋮un+vn)\mathbf{u} + \mathbf{v} = \begin{pmatrix} u_1 + v_1 \\ u_2 + v_2 \\ \vdots \\ u_n + v_n \end{pmatrix} u+v=u1+v1u2+v2⋮un+vn
数乘向量
一个标量 ccc 与向量 v\mathbf{v}v 相乘:
cv=(cv1cv2⋮cvn)c \mathbf{v} = \begin{pmatrix} c v_1 \\ c v_2 \\ \vdots \\ c v_n \end{pmatrix} cv=cv1cv2⋮cvn
点积(内积)
两个相同维度的向量 u\mathbf{u}u 和 v\mathbf{v}v 的点积:
u⋅v=∑i=1nuivi\mathbf{u} \cdot \mathbf{v} = \sum_{i=1}^n u_i v_i u⋅v=i=1∑nuivi
6. 矩阵的初等变换
矩阵的初等变换包括:
- 行交换:交换两行。
- 行缩放:将一行乘以一个非零标量。
- 行加法:将一行的倍数加到另一行。
这些变换用于求解线性方程组和计算矩阵的秩。
6. 矩阵的运算:加法、减法、乘法与转置
矩阵加法和减法
两个相同大小的矩阵 AAA 和 BBB 可以相加或相减:
(A±B)ij=aij±bij(A \pm B)_{ij} = a_{ij} \pm b_{ij} (A±B)ij=aij±bij
矩阵乘法
矩阵 AAA(m×nm \times nm×n)和矩阵 BBB(n×pn \times pn×p)的乘积 CCC(m×pm \times pm×p):
cij=∑k=1naikbkjc_{ij} = \sum_{k=1}^n a_{ik} b_{kj} cij=k=1∑naikbkj
矩阵转置
矩阵 AAA 的转置 ATA^TAT 是通过交换行和列得到的:
(AT)ij=aji(A^T)_{ij} = a_{ji} (AT)ij=aji
6. 特殊矩阵的概念
单位阵
单位阵 InI_nIn 是一个 n×nn \times nn×n 的方阵,主对角线元素为 1,其余为 0:
In=(10⋯001⋯0⋮⋮⋱⋮00⋯1)I_n = \begin{pmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{pmatrix} In=10⋮001⋮0⋯⋯⋱⋯00⋮1
三角阵
- 上三角阵:主对角线以下元素全为 0。
- 下三角阵:主对角线以上元素全为 0。
对称阵
矩阵 AAA 是对称阵如果 A=ATA = A^TA=AT,即 aij=ajia_{ij} = a_{ji}aij=aji。
稀疏矩阵
稀疏矩阵是大部分元素为零的矩阵,通常用特殊数据结构(如三元组)存储以节省空间。
7. 高斯消元法
高斯消元法用于求解线性方程组或计算矩阵的秩。通过初等变换将矩阵化为行阶梯形式(Row Echelon Form)。
步骤:
- 选择主元(通常从左上方开始)。
- 使用行交换确保主元非零。
- 使用行缩放将主元化为 1。
- 使用行加法将主元下方的元素消为 0。
- 重复以上步骤直到矩阵变为行阶梯形式。
求解线性方程组:
对于增广矩阵 [A∣b][A | \mathbf{b}][A∣b],通过高斯消元法得到上三角阵,然后回代求解。
模板代码
使用二维向量表示矩阵。
#include <iostream>
#include <vector>
using namespace std;// 矩阵类型定义
typedef vector<vector<double>> Matrix;
typedef vector<double> Vector;// 打印矩阵
void printMatrix(const Matrix& mat) {for (const auto& row : mat) {for (double val : row) {cout << val << " ";}cout << endl;}
}
矩阵运算代码
// 矩阵加法
Matrix matrixAdd(const Matrix& A, const Matrix& B) {int m = A.size(), n = A[0].size();Matrix C(m, vector<double>(n));for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {C[i][j] = A[i][j] + B[i][j];}}return C;
}// 矩阵减法
Matrix matrixSub(const Matrix& A, const Matrix& B) {int m = A.size(), n = A[0].size();Matrix C(m, vector<double>(n));for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {C[i][j] = A[i][j] - B[i][j];}}return C;
}// 矩阵乘法
Matrix matrixMul(const Matrix& A, const Matrix& B) {int m = A.size(), n = A[0].size(), p = B[0].size();Matrix C(m, vector<double>(p, 0));for (int i = 0; i < m; i++) {for (int k = 0; k < n; k++) {if (A[i][k] != 0) {for (int j = 0; j < p; j++) {C[i][j] += A[i][k] * B[k][j];}}}}return C;
}// 矩阵转置
Matrix matrixTranspose(const Matrix& A) {int m = A.size(), n = A[0].size();Matrix B(n, vector<double>(m));for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {B[j][i] = A[i][j];}}return B;
}
高斯消元法代码
// 高斯消元法求解线性方程组 Ax = b
Vector gaussElimination(Matrix A, Vector b) {int n = A.size();// 构造增广矩阵for (int i = 0; i < n; i++) {A[i].push_back(b[i]);}// 前向消元for (int i = 0; i < n; i++) {// 寻找主元int pivot = i;for (int j = i + 1; j < n; j++) {if (abs(A[j][i]) > abs(A[pivot][i])) {pivot = j;}}swap(A[i], A[pivot]);// 消元for (int j = i + 1; j < n; j++) {double factor = A[j][i] / A[i][i];for (int k = i; k <= n; k++) {A[j][k] -= factor * A[i][k];}}}// 回代Vector x(n);for (int i = n - 1; i >= 0; i--) {x[i] = A[i][n];for (int j = i + 1; j < n; j++) {x[i] -= A[i][j] * x[j];}x[i] /= A[i][i];}return x;
}
CSP-S 提高组初赛复习大纲
更新时间:2025 年 9 月 18 日 23:21:08
- 2.2.1 基础知识与编程环境 & C++ 程序设计
- 2.2.3 数据结构
- 2.2.4 算法
- 2.2.5 数学与其他