本问题等价于把n个不同的球划分/分配为m份。
组合数学概念:斯特林stirling数
斯特林数出现在许多组合枚举问题中,有两类。
第一类斯特林数 StirlingS1[n,m], 把p个对象排成k个非空循环排列的方法数。
第二类斯特林数 StirlingS2[n,m]给出把 p 个可区分小球分配到k个不可区分的盒子,且盒子没有空盒子的方法的数量。第一类斯特林数和第二类斯特林数有相同的初始条件,但递推关系不同。
本问题是典型的第二类斯特林数,存在递推关系:
很显然p要大于等于k。当p等于k时,只有1种分配方法。当k为0时,分配方法也是0。
然后分析递推关系:
p个球分为k份:对于某一个球,如果单独拿出来作为1份,那么剩下的问题就是p-1个球分为k-1份;如果跟其他球在一起,其他球的问题是p-1个球分为k份,这k份我都可以把这个球放进去,有k种情况。
设S(p,k),则递推公式是:
当1<= k <=p-1, S(p,k) = k*S(p-1,k) + S(p-1,k-1)
边界条件:
当p>=0,S(p,p) = 1
当p>=1,S(p,0) = 0
除了上面的递推式,《组合数学》中还有一种利用差分序列表的第0条对角线表示的式子。
代码:
int fun(int n, int m) { if(n<m) return -1; else if(m == 0) return 0; else if(n == m) return 1; else return m*fun(n-1,m) + fun(n-1, m-1); }