📜  Bell Numbers(划分集合的方法数)(1)

📅  最后修改于: 2023-12-03 15:13:38.826000             🧑  作者: Mango

Bell Numbers(划分集合的方法数)

介绍

Bell Numbers是对集合进行划分的方法数。具体地,给定一个大小为n的集合,Bell Number表示将该集合分成若干个互不相交的集合的方法数。例如,对于集合{1,2,3},它可以被划分为{1},{2},{3}、{1,2},{3}、{1,3},{2}、{1},{2,3}等4种方法,因此其Bell Number为4。

Bell Numbers的计算方法较为复杂,Bell Number的通项公式目前还未被发现。因此,计算Bell Number通常使用递归或动态规划的方法。

计算方法
递归

n个元素的集合的Bell Number可以通过以下方法计算:

  1. 当n为1时,Bell Number为1。
  2. 当n大于1时,对于每个大小为i(1 <= i <= n)的子集合,递归计算其Bell Number再乘以Stirling Number of the Second Kind (S(n,i)),最后将所有结果相加即可得到n个元素的集合的Bell Number。

其中,Stirling Number of the Second Kind (S(n,i))表示将n个不同元素划分为i个非空集合的方法数。

递归计算公式为:

def bell_number_recursive(n):
    if n == 1:
        return 1
    else:
        return sum(bell_number_recursive(i) * stirling_second(n,i) for i in range(1,n+1))
动态规划

n个元素的集合的Bell Number还可以通过动态规划的方法计算。设DP[i][j]为将大小为i的集合划分为j个非空集合的方法数,则Bell Number为DP[n][1] + DP[n][2] + ... + DP[n][n]。

边界条件为DP[i][1] = 1(将大小为i的集合划分为1个集合只有一种方法),同时DP[1][j] = 1(将大小为1的集合划分为j个集合只有一种方法)。

状态转移方程为:

$$DP[i][j] = j * DP[i-1][j] + DP[i-1][j-1]$$

其中,第一项表示将i个元素分配给已经划分好的j个集合中的一个,第二项表示将i个元素新分配一个新的集合中。

动态规划代码如下:

def bell_number_dp(n):
    DP = [[0] * (n+1) for i in range(n+1)]
    DP[1][1] = 1
    for i in range(2,n+1):
        DP[i][1] = 1
        for j in range(2,i+1):
            DP[i][j] = j * DP[i-1][j] + DP[i-1][j-1]
    return sum(DP[n][i] for i in range(1,n+1))
性质

Bell Numbers具有以下性质:

  1. Bell Numbers可用来计算多项式的数列,其生成函数为(2.1)式。
  2. n个元素的集合的划分数等于n个互异元素的划分委员会数。
  3. Bell Numbers与Catalan Numbers之间有递归关系。
  4. Bell Numbers满足递推关系:Bell(n+1) = sum(Bell(i) * C(n,i-1)) (其中C(n,i)为第n个数的组合数)
参考文献
  1. https://en.wikipedia.org/wiki/Bell_number
  2. 陈启峰, 计算机算法设计与分析(第4版), 清华大学出版社.
  3. https://oeis.org/A000110