题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=2512
思路
第一类斯特林数
s2[i][j]=
将
j
个互不相同的物品划分成
s2[i][j]=s2[i−1][j−1]+js2[i−1][j]
递推式的解释:对于第 i 个物品有两种情况:
1、前
i−1 个物品已经划分成了 j−1 个非空集合,第 i 个物品单独构成第j 个集合。
2、前 i−1 个物品已经划分成了 j 个非空集合,第i 个物品可以选择放入 j 个集合当中之一,共j 个方案,因此是 js2[i−1][j] 。贝尔数 bell[i]=i 个互不相同的物品,划分成若干个非空集合的方案数。
bell[i]=∑k=0is2[i][k]
这个式子非常显然,即枚举划分成 k 个非空集合,对s2[i][k] 求和即可得到贝尔数。代码
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define MAXN 2200 #define MOD 1000 using namespace std; int s2[MAXN][MAXN],bell[MAXN]; void GetSecondStirling() //求第二类Stirling数 { s2[1][1]=1; for(int i=2;i<MAXN;i++) { s2[i][i]=1; s2[i][1]=1; for(int j=2;j<i;j++) s2[i][j]=(s2[i-1][j-1]+s2[i-1][j]*j)%MOD; } } void GetBell() //求贝尔数 { for(int i=1;i<MAXN;i++) { bell[i]=0; for(int j=0;j<=i;j++) bell[i]=(bell[i]+s2[i][j])%MOD; } } int main() { int n,T; GetSecondStirling(); GetBell(); scanf("%d",&T); while(T--) { scanf("%d",&n); printf("%d\n",bell[n]); } return 0; }