[toj4087]m个不同的箱子放n种不同的球

来源:互联网 发布:java电商架构 编辑:程序博客网 时间:2024/04/30 17:39

首先有个三角关系:

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;}


0 0
原创粉丝点击