POJ 3088 斯特林

题意:有一个n个按钮的锁,按下一些按钮打开门,有多少开门方式,其中,一些按钮可以选,可以不选,选中的按钮 可以分成一些集合,集合之间无序,是同时按下的。

分析:

1、首先选择 i 个按钮,组合数

2、枚举分成的集合

3、i 个按钮分成无序集合,第二类斯特林数

4、集合之间有序,排列数

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int maxn = 105;

long long fac[maxn];
long long C[maxn][maxn];
long long stir[maxn][maxn];

void init() {

    fac[0] = fac[1] = 1;
    for(int i=2;i<maxn;i++)
        fac[i] = fac[i-1]*(long long)i;

    memset(C,0,sizeof(C));
    C[0][0] = 1;
    C[1][0] = C[1][1] = 1;

    for(int i=2;i<maxn;i++) {
        C[i][0] = C[i][i] = 1;
        for(int j=1;j<i;j++)
            C[i][j] = C[i-1][j-1] + C[i-1][j];
    }

    stir[1][1] = 1;
    for(int i=2;i<maxn;i++)
        for(int j=1;j<=i;j++)
            stir[i][j] = stir[i-1][j-1] + (long long)j*stir[i-1][j];


}

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    init();
    int kase = 1;
    while(t--) {
        int n;
        scanf("%d",&n);

        long long ans  = 0;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=i;j++) {
                ans+=(C[n][i]*fac[j]*stir[i][j]);
            }
        }

        printf("%d %d %I64d
",kase++,n,ans);

    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/7216219.html