mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
754 字
2 分钟
组合计数
2026-03-31

组合计数#

两个基本原理#

  • 加法原理: 做一件事有若干类互不重叠的办法,每类分别有 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) 种。两者相减即得合法方案数。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

组合计数
https://blogstella.xyz/posts/数据结构之组合计数/
作者
Stella
发布于
2026-03-31
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录