754 字
2 分钟
组合计数
组合计数
两个基本原理
- 加法原理: 做一件事有若干类互不重叠的办法,每类分别有 a₁, a₂, … 种方式,则总方案数为 a₁ + a₂ + …。
- 乘法原理: 做一件事分成若干连续的步骤,每步分别有 b₁, b₂, … 种选择,则总方案数为 b₁ × b₂ × …。
几乎所有计数问题都是这两个原理的组合:先”分类”(加法)再”分步”(乘法)。
排列与组合
- 排列数: 从 n 个不同元素中选出 m 个排成一列,方案数 A(n, m) = n! / (n - m)!。
- 组合数: 从 n 个不同元素中选出 m 个(不考虑顺序),方案数 C(n, m) = n! / (m!(n - m)!)。 组合与排列差一个 m! 倍:排列 = 组合 × 选出的 m 个元素内部的排列数。
常用性质:
- 对称性: C(n, m) = C(n, n - m)(选 m 个等价于排除 n - m 个);
- 递推式: C(n, m) = C(n-1, m) + C(n-1, m-1)(按”第 n 个元素选或不选”分类,加法原理);
- 二项式定理: (x + y)^n = Σ C(n, k)·x^k·y^{n-k},这也是组合数名称的由来。
组合数的四种求法(按数据范围选择)
| 数据范围 | 做法 | 复杂度 |
|---|---|---|
| n ≤ 2000 左右,多次询问 | 递推预处理 C[i][j] = C[i-1][j] + C[i-1][j-1] | O(n²) 预处理,O(1) 查询 |
| n ≤ 10⁵,模数为质数 | 预处理阶乘 + 阶乘逆元(费马小定理求逆) | O(n) 预处理,O(1) 查询 |
| n 巨大、模数 p 较小且为质数 | Lucas 定理:C(n, m) ≡ C(n/p, m/p)·C(n%p, m%p) (mod p) | O(p + log n) |
| 无模数、要求精确大数 | 高精度逐项乘除(BigInteger) | O(n²) 位运算 |
递推求组合数模板
import java.util.*;
public class Main { static final int N = 2010; static final int MOD = (int) 1e9 + 7; static int[][] c = new int[N][N];
// 递推预处理所有组合数 C[i][j](i, j < N) static void init() { for (int i = 0; i < N; i++) for (int j = 0; j <= i; j++) if (j == 0) c[i][j] = 1; else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; }
public static void main(String[] args) { Scanner sc = new Scanner(System.in); init(); int n = sc.nextInt(); while (n-- > 0) { int a = sc.nextInt(), b = sc.nextInt(); System.out.println(c[a][b]); } }}卡特兰数
问题原型: 求”n 个 +1 和 n 个 -1 组成的序列中,任意前缀和 ≥ 0 的合法序列个数”,等价于很多经典计数问题:n 对括号的合法匹配方案数、n 个元素依次入栈的不同出栈序列数、n+1 个叶子的满二叉树个数、凸 n+2 边形三角剖分方案数等。
公式: 卡特兰数
Cₙ = C(2n, n) - C(2n, n+1) = C(2n, n) / (n + 1)
递推式: C₀ = 1,Cₙ₊₁ = Σ Cᵢ·Cₙ₋ᵢ(按”第一对括号匹配的位置”分类,乘法原理 + 加法原理)。
理解”合法括号”计数: 2n 个位置任选 n 个放左括号共 C(2n, n) 种;其中非法的部分(存在前缀右括号多于左括号)可以通过”第一次越界处整体翻转”一一对应到”n+1 个左括号、n-1 个右括号”的序列,共 C(2n, n+1) 种。两者相减即得合法方案数。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
1
高斯消元
算法 高斯消元解线性方程组的原理(选主元、消元、回代)与 Java 实现,含无解/无穷多解的判断。
2
博弈论
算法 博弈论入门:Nim 游戏与异或和的关系、SG 函数与有向图游戏,附经典例题的 Java 实现。
3
并查集
算法 并查集的原理、路径压缩与按 size 合并,配合合并集合、连通块中点的数量两道例题的 Java 实现。
4
质数与筛法
算法 质数的试除法判定、分解质因数、埃氏筛与线性筛、试除法求约数、最大公约数(欧几里得算法)的入门讲解与 Java 实现。
5
DFS和BFS
算法 深度优先搜索与广度优先搜索入门,包括全排列、N 皇后、单词搜索与走迷宫等经典例题的讲解与 Java 实现。