概述
斯特林数(Stirling Numbers) 是一类重要的组合数,用于描述集合的划分和排列的结构关系。1
主要有两类:
- 第一类斯特林数:将 个元素排成 个非空轮换
- 第二类斯特林数:将 个元素划分成 个非空集合
第一类斯特林数(Stirling Numbers of the First Kind)
定义
记作 或 \left[\begin{n}\\k\end{array}\right],表示将 个不同元素排成 个**非空轮换(Cycle)**的方案数。
轮换:环形排列,如 和 是同一个轮换。
递推关系
含义:
- 新元素单独成一个轮换:
- 新元素插入已有轮换的任意位置:
性质
- (当 )
第二类斯特林数(Stirling Numbers of the Second Kind)
定义
记作 或 \left\{\begin{n}\\k\end{array}\right\},表示将 个不同元素划分成 个**非空集合(Subset)**的方案数。
递推关系
含义:
- 新元素单独成一个集合:
- 新元素加入已有 个集合中的任意一个:
封闭形式
这是容斥原理的应用。
贝尔数(Bell Numbers)
定义
贝尔数 表示将 个元素划分成任意数量非空集合的方案数:
递推关系(Dobinski公式)
性质
计算方法
O(nk) 动态规划
// 第一类斯特林数
vector<vector<long long>> stirling1(int n) {
vector<vector<long long>> s(n+1, vector<long long>(n+1, 0));
s[1][1] = 1;
for (int i = 2; i <= n; i++) {
for (int k = 1; k <= i; k++) {
s[i][k] = (s[i-1][k-1] + (i-1) * s[i-1][k]) % MOD;
}
}
return s;
}
// 第二类斯特林数
vector<vector<long long>> stirling2(int n) {
vector<vector<long long>> S(n+1, vector<long long>(n+1, 0));
S[1][1] = 1;
for (int i = 2; i <= n; i++) {
for (int k = 1; k <= i; k++) {
S[i][k] = (S[i-1][k-1] + k * S[i-1][k]) % MOD;
}
}
return S;
}O(n log n) 使用多项式
第二类斯特林数可以通过多项式求幂在 内计算一行:
应用场景
1. 排列分解
将 个元素的排列分解成 个轮换,第一类斯特林数给出方案数。
例: 的排列可以分解为:
- 1个轮换: → 种
- 2个轮换: → 种
- 3个轮换: → 种
2. 集合划分计数
将 个任务分配给 个工人(工人不可区分),方案数为 。
3. 与其他数列的关系
- 阶乘:
- 贝尔多项式:指数生成函数与贝尔多项式相关
对照表
| (第一类) | (第二类) | |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
参考
Last updated: 2026-04-06
Footnotes
-
本内容参考 OI-Wiki 斯特林数,内容经过验证和扩展。 ↩