您的位置:首页 > 其它

盒子放球

2015-10-22 19:48 169 查看

盒子放球问题

第一类:

将k个球放入n个不同的盒子中,每个盒子放球数>=0,求方法数

假设n个盒子分别放

x1,x2,x3...xn
,则
x1+x2+x3+...+xn=k
,令
yi=xi+1(1<=i<=n)
,则
yi>=1
y1+y2+...+yn=n+k
,相当于求yi这个方程的解组数,可以看成插板问题,往
n+k
个物品中插入
n-1
个板,所以答案是
C(n+k-1,n-1)=C(n+k-1,k)

/*
*输入说明:k个相同的球放入n个不同的盒子
*输入每行有两个正整数n和k
*/
int com(int n, int m) {
m = min(m, n - m);
int res = 1;
for (int i = 0, j = 1; i < m; i ++) {
res *= n - i;
while (j <= m && res % j == 0) {
res /= j;
j ++;
}
}
return res;
}

int main() {

int n, k;
while (~scanf("%d %d", &n, &k)) {
printf("%d\n", com(n+k-1, k));
}

return 0;
}

 

第二类:

m个相同的球放入n个相同的盒子,每个盒子放球数>=0,求方法数

令dp[i][j]表示i个球放入j个盒子的方法数。

当i>j时,分两种情况:

1、每个盒子至少放一个,为dp[i-j][j]

2、存在某个盒子不放,为dp[i][j-1]

所以dp[i][j] = dp[i-j][j] + dp[i][j-1];

当i<=j时,等价于i个球放入i个盒子

const int maxn = 20;

int dp[maxn][maxn];//i个球放入j个盒子方法数

void init() {
for (int j = 1; j <= 10; j ++) dp[0][j] = dp[1][j] = dp[j][1] = dp[j][0] = 1;
for (int i = 2; i <= 10; i ++) {
for (int j = 2; j <= 10; j ++) {
if (i >= j) dp[i][j] = dp[i-j][j] + dp[i][j-1];
else dp[i][j] = dp[i][i];
}
}
}

int main() {

init();
int T, m, n;
scanf("%d", &T);
while (T --) {
scanf("%d %d", &m, &n);
printf("%d\n", dp[m]
);
}
return 0;
}

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: