题目:洛谷P1025
解法:
看到这个题目,我第一反应是组合数学的知识,题目等价于将n个相同的物品(数字1)分成k堆,求方案数。
这道题的解法在高中的排列组合肯定用到过,但是想不起来了。
方法如下:
首先,要保证计算过程中相同的方案(每堆的数量相同,但顺序不同)只能计数1次,我采用的是在前一堆的基础上增加后一堆的数量,保证后一堆的数量不小于前一堆,这样每堆的数量是递增的,也就不会担心相同数量的堆顺序不同而重复计数了。
那么,怎样保证后一堆的数量不小于前一堆呢?可以直接考虑后一堆的数量=前一堆的数量+i(i>=0),这样迭代的话需要k-1个循环,感觉不太好做,放弃了。
之后,我采用了少量多次,每次分配的堆数不超过上一次的办法确保后一堆数量不小于前一堆。大体思路是,先分配给k个堆相同的数量i,再分配给h个堆(h
可以看出,这是一种递归的算法。
每一次操作的h、j不同,产生的解决方案也就不同。
而可以发现,当j>1时,分给h个堆的相同数量j可以分成分给h个堆的相同数量1,分j次。取j>1会使我们漏掉一些分配方案。而取j=0相当于什么都没干。
所以我们将,下次分配的数量定为1,当下次分配的数量j确定了,变量也就剩下次分配的堆数h。
分配的堆数h满足1<=h<=k,要保证下次分配的堆的数量小于当前堆的数量,那么我们令h=k-下次不打算分配的堆数i(0<=i 大体上的思路搞定了,但是题目要求每堆不为空,而如果第一次分配的数目就小于k,那么是不符合题意的。所以,现将k堆分配数量1,可分配的数量变成n=n-k,堆数k=k,之后再递归地进行上述的过程。 代码如下: #include