首先有个三角关系:
1
1 1
1 3 1
1 7 5 1
1 15 17 7 1
..
递推为f[i][j] = j*f[i-1][j] + f[i-1][j-1]
上述是第二类斯特灵数的地推关系
第二类斯特灵数描述的问题类似于:m个相同的箱子放n种不同的球,那么分法如上述.
如果箱子不同,那么先对箱子排列,所以答案为ans(n,m) = m! * f[n][m]
而本题就是求C(m,1) * 1! * f[n][1] + C(m,2) * 2! * f[n][2] + ... + C(m, m-1) * (m-1)! * f[n][m-1]
数据不大,但我还是预处理了,组合数(杨辉三角的方法)(C[][]数组, C[i][j]表示从i个中选j个), 阶乘(G[]数组, G[i]表示i的阶乘), 和f[i][j](dp[][]数组,如上,dp[i][j]表示i个箱子放j种球)这三部分:
#include <cstdio>
#include <cstring>
typedef long long ll;
const int MAXN = 505;
const int MAXM = 11;
const ll MOD = 200000007;
ll dp[MAXN][MAXN];
ll G[MAXN];
ll C[MAXN][MAXN];
ll ans[MAXN][MAXM];
void init(void) {
for (int i = 1; i < MAXN; ++i) {
dp[i][1] = 1;
dp[i][i] = 1;
for (int j = 2; j < i; ++j) {
dp[i][j] = (dp[i-1][j]*j + dp[i-1][j-1]) % MOD;
}
}
G[0] = 1;
for (int i = 1; i < MAXN; ++i) {
G[i] = G[i-1]*i % MOD;
}
memset(C, 0, sizeof(C));
for (int i = 1; i < MAXN; ++i) {
C[i][1] = i;
for (int j = 2; j <= i; ++j) {
C[i][j] = C[i-1][j] + C[i-1][j-1];
C[i][j] %= MOD;
}
}
for (int m = 1; m < MAXM; ++m) {
for (int n = 1; n < MAXN; ++n) {
ans[n][m] = 0;
for (int i = 1; i < m; ++i) {
ans[n][m] += C[m][i] * G[i] * dp[n][i];
ans[n][m] %= MOD;
}
}
}
}
int main() {
init();
int T, n, m;
static int cas = 1;
scanf(" %d", &T);
while (T--) {
scanf(" %d %d", &n, &m);
printf("Case %d: %lld\n", cas++, ans[n][m]);
}
return 0;
}