SDUT:2883 Hearthstone II(第二类Stirling数)

题意:将m个物品放入n个箱子之中,要求每个物体至少使用一次。问有多少种情况。

思路:第二类斯特灵数。

第二类Stirling数 S(p,k)
   
S(p,k)的一个组合学解释是:将p个物体划分成k个非空的不可辨别的(可以理解为盒子没有编号)集合的方法数。
k!S(p,k)是把p个人分进k间有差别(如:被标有房号)的房间(无空房)的方法数。
   
S(p,k)的递推公式是:S(p,k)=k*S(p-1,k)+S(p-1,k-1) ,1<= k<=p-1
边界条件:S(p,p)=1 ,p>=0    S(p,0)=0 ,p>=1
  
递推关系的说明:
考虑第p个物品,p可以单独构成一个非空集合,此时前p-1个物品构成k-1个非空的不可辨别的集合,方法数为S(p-1,k-1);
也可以前p-1种物品构成k个非空的不可辨别的集合,第p个物品放入任意一个中,这样有k*S(p-1,k)种方法。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn=105;
LL mod=1000000007;
LL S[maxn][maxn];
LL M[maxn];
void init()
{
    M[0]=1;
    for(int i=1; i<=100; ++i)
        M[i]=M[i-1]*i%mod;
    S[1][1]=1;
    for(int p=2; p<=100; ++p)
        for(int k=1; k<=p; ++k)
        {
            S[p][k]=k*S[p-1][k]%mod+S[p-1][k-1];
            S[p][k]%=mod;
        }
}
int main()
{
    init();
    int n,m;
    while(cin>>n>>m)
        cout<<M[m]*S[n][m]%mod<<endl;
    return 0;
}


你可能感兴趣的:(Stirling数)