排列组合基础 (Basics)

排列 (Permutation)

个不同元素中取出 个元素排成一列,称为排列,记作

特殊情况:当 时,

组合 (Combination)

个不同元素中取出 个元素成一组(不考虑顺序),称为组合,记作

重要性质(对称性)

组合数的性质

组合数满足递推关系(Pascal’s triangle / 杨辉三角):

由此可得:


二项式定理 (Binomial Theorem)

推论


常用计数技巧 (Common Counting Techniques)

加法原理与乘法原理

加法原理:完成一件事有 类方式,第 类方式有 种方法,则总方法数为:

乘法原理:完成一件事需要 个步骤,第 步有 种方法,则总方法数为:

容斥原理 (Inclusion-Exclusion Principle)

用于计算若干集合的并集大小。设 为有限集合,则:

简单例子(三个集合):

抽屉原理 (Pigeonhole Principle)

简单形式:如果把 个物体放入 个盒子,则至少有一个盒子中有两个或更多物体。

广义形式:如果把 个物体放入 个盒子,则至少有一个盒子中含有至少 个物体。

应用示例:在 个整数中,必有两个整数的差是 的倍数。


递推关系 (Recurrence Relations)

斐波那契数列 (Fibonacci Sequence)

前几项:

通项公式(Binet公式):

其中

Catalan 数

Catalan 数 满足:

前几项:

组合意义

  • 含有 个叶子的满二叉树的个数
  • 对括号的有效匹配数
  • 棋盘从左下角到右上角不穿过对角线的路径数

Stirling 数

第一类 Stirling 数 :将 个元素分成 个非空循环排列的方法数。

递推公式:

第二类 Stirling 数 :将 个元素分成 个非空集合的方法数。

递推公式:


母函数初步 (Generating Function Basics)

母函数(生成函数)用于解决递推关系和计数问题。

普通母函数

序列 的普通母函数为:

示例:对于 Fibonacci 数列,母函数为:

指数母函数

序列 的指数母函数为:

经典应用

用母函数可以证明组合恒等式,例如:


组合数取模 (Modular Combinatorics)

Lucas 定理

为素数时,组合数取模可以用 Lucas 定理高效计算:

其中 进制表示。

适用场景 很大(甚至达到 ),但 较小(如 )。

预处理阶乘与逆阶乘

在模 下计算组合数,通常需要预计算阶乘和逆阶乘:

const int MOD = 1e9 + 7;
const int MAXN = 2e6 + 5;
 
int64_t fact[MAXN], infact[MAXN];
 
int64_t mod_pow(int64_t a, int64_t b) {
    int64_t res = 1;
    while (b) {
        if (b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return res;
}
 
void init_factorials(int n) {
    fact[0] = 1;
    for (int i = 1; i <= n; i++) {
        fact[i] = fact[i-1] * i % MOD;
    }
    infact[n] = mod_pow(fact[n], MOD - 2);  // Fermat's little theorem
    for (int i = n; i > 0; i--) {
        infact[i-1] = infact[i] * i % MOD;
    }
}
 
int64_t C(int n, int m) {
    if (n < 0 || m < 0 || m > n) return 0;
    return fact[n] * infact[m] % MOD * infact[n-m] % MOD;
}

注意

  • 为素数时,(Fermat 小定理)
  • 使用 Lucas 定理时,递归计算即可

参考资料