第二类Stirling数(斯特林数)LightOJ - 1326

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ljq1998/article/details/81178613

S(n,k)是n个数的集合的划分为k个非空集合方法的数目。(n个不同小球放到m个相同的盒子,每个盒子至少放一个球的种数)

例如S3,2 = 3因为3个元素的集合{a, b, c}有3种不同的划分方法:

{{a}, {b, c}}, {{b}, {a, c}}, {{c}, {a, b}}。可以知道Bell(n) = Sn,ki,( 1 <= ki <= n)。

递推式:S(n, k) = k * S(n - 1, k) + S(n - 1, k - 1)

边界条件: S(n, n) = 1, n >= 0

             S(n, 0) = 0, n >= 1

解释:第n个物品来单独考虑。。我们要分为k个集合。。

1.可以把当前第n个物品作为一个集合,也就是S(n - 1, k - 1)中方法。

2.也可以把当前第n个物品放在其他的集合中来构成k个集合。也就是S(n - 1, k)中方法。

扩展:k! *S(n,k) 计数的是把n元素集合划分到k个可区分的盒子里且没有空盒子的划分个数。

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int mod = 10056;
int s[2000][2000];
int p[2000];
void init()
{
    memset(s,0,sizeof(s));
    s[0][0] = 1;
    for(int i = 1;i < 1008;i++){
        s[i][0] = 0;
        for(int j = 1;j < i;j++){
            s[i][j] = (j * s[i - 1][j] + s[i - 1][j - 1]) % mod;
        }
        s[i][i] = 1;
    }
    p[0] = p[1] = 1;
    for(int i = 2;i <= 1008;i++){
        p[i] = (p[i - 1] * i) % mod;
    }
}
int main()
{
    init();
    int t,kk = 1;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        int ans = 0;
        for(int i = 1;i <= n;i++){
            ans = (ans + p[i] * s[n][i]) % mod;
        }
        printf("Case %d: %d\n",kk++,ans);
    }
	return 0;
}

https://blog.csdn.net/winycg/article/details/70233717

猜你喜欢

转载自blog.csdn.net/ljq1998/article/details/81178613