集合划分

覆盖 : 若把集合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]; 
}
    


posted @ 2020-12-11 18:24  phr2000  阅读(497)  评论(0编辑  收藏  举报