引用:
这题其实是排列组合里的题,可以把一个数值为n的数当做n个小球,划分的份数k当做k个盒子,那么本题可以转化为“将n个小球放到k个盒子中,小球之间与盒子之间没有区别,并且最后的结果不允许空盒”
将n个小球放到k个盒子中的情况总数 =
a.至少有一个盒子只有一个小球的情况数
+b.没有一个盒子只有一个小球的情况数
这样进行划分是因为这种分类可以使a和b都有能写出来的表达式:
a.因为盒子不加区分,那么1的情况数与“将n-1个小球放到k-1个盒子中”的情况数一样
b.没有一个盒子只有一个小球,那么把每个盒子中拿出来一个小球,对应的是“把(n-k)个小球放到k个盒子中的情况数”
然后将上面的思路化为动态转移方程:
设f[n,k]代表将n个小球放到k个盒子中且没有空盒的情况,那么f[n,k] = f[n-1,k-1] + f[n-k,k]
而当k=1时只有1种方法(小球全部放进1个盒子)
//My AC Code:
#include <cstdio>
using namespace std;
int n,k,f[3000][3000];
int main(){
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)f[i][1]=1;
for(int i=2;i<=n;i++){
for(int j=2;j<=i;j++){
f[i][j]=f[i-1][j-1]+f[i-j][j];
}
}
printf("%d",f[n][k]);
return 0;
}