古典叙事 · 技术札记

序章

山河有卷
人间有声

写代码,也写长风、旧城与未熄的灯。
愿每一篇随笔,都有自己的山水与回声。
阅览随笔

组合数学常见组合

模型一:插板法(Stars and Bars / 隔板模型)物理场景

:把 \(n\) 个一模一样的苹果,分给 \(m\) 个不同的小朋友。触发关键词:相同的物品、分给不同的人、方程 \(x_1 + x_2 + \dots + x_m = n\) 的整数解个数。解法推导:
情况 A(每个人至少分 1 个 / 正整数解):\(n\) 个苹果排成一排,中间有 \(n-1\) 个空隙。拿 \(m-1\) 块隔板插进空隙里,就把苹果分成了 \(m\) 份。公式:\(\binom{n-1}{m-1}\)
情况 B(允许有人分不到 / 非负整数解):这太常见了!解法是“借花献佛”。我们先去虚空借 \(m\) 个苹果,提前发给每个小朋友 1 个。这样问题就变成了“把 \(n+m\) 个苹果分给 \(m\) 个人,每人至少 1 个”。公式:\(\binom{n+m-1}{m-1}\)

模型二:插空法(不相邻模型)物理场景:

\(n\) 个位置种 \(m\) 棵树,任何两棵树不能相邻。触发关键词:不能相邻、互不接触。解法推导:不要去盯着树怎么排,去盯着空位置!种了 \(m\) 棵树,必然剩下 \(n-m\) 个空位置。这 \(n-m\) 个空位置排成一排,产生了 \((n-m) + 1\) 个空隙(包含两端)。把 \(m\) 棵树插进这些空隙里。公式:\(\binom{n-m+1}{m}\) (如果是不同的树,再乘上排列数 \(m!\)

模型三:卡特兰数(Catalan Number)

物理场景:从网格的左下角走到右上角,永远不能越过对角线 \(y = x\)。触发关键词:出栈入栈序列(进栈次数永远 \(\ge\) 出栈次数)。合法括号匹配(( 的数量永远 \(\ge\) ) 的数量)。\(n\) 个节点的二叉树形态个数。凸多边形划分为三角形的方案数。圆上 \(2n\) 个点连成 \(n\) 条不相交的弦。解法推导:利用“翻折容斥法”,总路径数减去越过对角线的非法路径数。通项公式:\(Cat(n) = \frac{1}{n+1}\binom{2n}{n} = \binom{2n}{n} - \binom{2n}{n-1}\)递推公式:\(Cat(n) = \sum_{i=0}^{n-1} Cat(i) \times Cat(n-1-i)\)

#include <iostream>
#include <vector>

using namespace std;

int main() {
    // 优化输入输出
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    if (!(cin >> n)) return 0;
    
    // f[i] 表示 i 个数进出栈的方案数(即第 i 个卡特兰数)
    vector<long long> f(n + 1, 0);
    
    // 边界条件:0 个数和 1 个数进出栈的方案数都是 1
    f[0] = 1;
    if (n >= 1) f[1] = 1;
    
    // 按照递推公式计算卡特兰数
    for (int i = 2; i <= n; i++) {
        for (int j = 0; j < i; j++) {
            f[i] += f[j] * f[i - 1 - j];
        }
    }
    
    // 直接输出第 n 个卡特兰数
    cout << f[n] << "\n";
    
    return 0;
}

模型四:错排问题(Derangement)物理场景:

\(n\) 个人去参加宴会,出门的时候所有人都拿错了帽子(没有任何一个人拿到属于自己的帽子)。触发关键词:全都不在原位、置换群中没有长度为 1 的环。解法推导:采用 DP 递推思想。假设第 \(n\) 个人拿了第 \(k\) 个人的帽子,那么对于第 \(k\) 个人,他有两个选择:拿第 \(n\) 个人的帽子(两人互换),剩下 \(n-2\) 个人继续错排。不拿第 \(n\) 个人的帽子(相当于第 \(k\) 个人继承了第 \(n\) 个人的限制),剩下 \(n-1\) 个人继续错排。递推公式:\(D_n = (n-1)(D_{n-1} + D_{n-2})\)(边界:\(D_1 = 0, D_2 = 1\))

模型五:斯特林数(Stirling Numbers)

当“物品”和“盒子”开始区分同与不同时,斯特林数就登场了。第二类斯特林数 \(S(n, k)\)(最常用):物理场景:把 \(n\) 个不同的小球,放进 \(k\) 个一模一样的盒子里,要求盒子不能空。触发关键词:集合划分、区分物品,不区分盒子。递推公式:考虑第 \(n\) 个球是单独放一个新盒子,还是挤进之前别人用过的盒子里。\(S(n, k) = S(n-1, k-1) + k \cdot S(n-1, k)\)第一类斯特林数 \(s(n, k)\):物理场景:将 \(n\) 个不同的人排成 \(k\) 个圆桌(轮换)。递推公式:\(s(n, k) = s(n-1, k-1) + (n-1) \cdot s(n-1, k)\)

扩展

任何普通幂 \(i^k\) 都可以展开为:$$i^k = \sum_{j=0}^k \begin{Bmatrix} k \ j \end{Bmatrix} j! \binom{i}{j}$$组合意义解释:把 \(k\) 个不同的球放进 \(i\) 个不同的盒子里(允许有空盒)。我们可以枚举非空盒子的个数 \(j\)\(j\)\(0\)\(k\)),先选出哪 \(j\) 个盒子装球 \(\binom{i}{j}\),再把 \(k\) 个球分成 \(j\) 个集合 \(\begin{Bmatrix} k \\ j \end{Bmatrix}\)(第二类斯特林数),最后给这 \(j\) 个集合分配具体
的盒子 \(j!\)

模型六:容斥原理(Inclusion-Exclusion)

这不是一个具体的公式,而是组合数学中最伟大的思维武器(你写《越狱》那题用的“正难则反”就是它的退化版)。物理场景:求同时满足多个恶心限制条件的方案数。触发关键词:至少、恰好、绝对不能包含、多个限制叠加。核心逻辑:当“同时满足所有条件 A 且 B 且 C”极难计算时,转化为:总方案数 \(-\) 不满足 A 的 \(-\) 不满足 B 的 \(+\) 同时不满足 A 和 B 的 \(\dots\)竞赛中的终极形态:莫比乌斯反演(数论容斥)、二项式反演、Min-Max 容斥。在高级比赛中,当你发现正面推导走投无路时,99% 的情况下,容斥原理是唯一能劈开迷雾的斧头。

posted @ 2026-08-11 14:07  Morphis‘  阅读(24)  评论(0)    收藏  举报