集合划分
覆盖 : 若把集合A分成若干个称为分块的非空子集, 使得A中的每个元素至少属于一个分块, 那么这些分块的全体集合称为A的一个覆盖.
划分 : A中的每个元素仅属于一个分块, 那么这些分块的全体构成的集合称为A的划分.
那么有 n 个元素的集合A有多少种划分?
\[\begin{align*}
f[1] &= 1 \quad f[2] = 2 \\
f[n] &= C_{n-1}^0f[0] + C_{n-1}^1f[1] + C_{n-1}^2f[2] + ...... + C_{n-1}^{n-1}f[n-1]
\end{align*}
\]
假设 n - 1 个数已经划分好了, 现在拿来第 n 个数, 原先的 n - 1 个数可以有 n - 1 种划分, 若原先为 i 个分块, 将第 n 个数拿来, 则有 \(C_{n-1}^if[i]\) 种可能.
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define pb push_back
#define PII pair<int, int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 1010;
ll C[N][N];
ll f[N];
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 - 1] + C[i - 1][j];
}
int main() {
IO;
init();
int n;
cin >> n;
memset(f, 0, sizeof f);
f[0] = 1;
for (int i = 1; i <= n; ++i)
for (int j = 0; j < i; ++j) f[i] += C[i - 1][j] * f[j];
cout << f[n];
}