這是一個使用動態編程的解決方案。
它從一個空集開始,然後每次添加一個元素並計算所有有效的分區。
狀態空間是巨大,但是請注意,要能計算出下一步,我們只需要知道一個分區以下的事情:
- 對於每一個民族,有多少套包含只由該國籍的一名成員組成。 (例如:{a})
- 它包含多少個具有混合元素的集合。 (例如:{a,b,c})
對於這些配置中的每一種,我只存儲總數。例如:
[0, 1, 2, 2] -> 3
{a}{b}{c}{mixed}
e.g.: 3 partitions that look like: {b}, {c}, {c}, {a,c}, {b,c}
這裏是在Python代碼:
import collections
from operator import mul
from fractions import Fraction
def nCk(n,k):
return int(reduce(mul, (Fraction(n-i, i+1) for i in range(k)), 1))
def good_partitions(l):
n = len(l)
i = 0
prev = collections.defaultdict(int)
while l:
#any more from this kind?
if l[0] == 0:
l.pop(0)
i += 1
continue
l[0] -= 1
curr = collections.defaultdict(int)
for solution,total in prev.iteritems():
for idx,item in enumerate(solution):
my_solution = list(solution)
if idx == i:
# add element as a new set
my_solution[i] += 1
curr[tuple(my_solution)] += total
elif my_solution[idx]:
if idx != n:
# add to a set consisting of one element
# or merge into multiple sets that consist of one element
cnt = my_solution[idx]
c = cnt
while c > 0:
my_solution = list(solution)
my_solution[n] += 1
my_solution[idx] -= c
curr[tuple(my_solution)] += total * nCk(cnt, c)
c -= 1
else:
# add to a mixed set
cnt = my_solution[idx]
curr[tuple(my_solution)] += total * cnt
if not prev:
# one set with one element
lone = [0] * (n+1)
lone[i] = 1
curr[tuple(lone)] = 1
prev = curr
return sum(prev.values())
print good_partitions([1, 1, 1, 1]) # 15
print good_partitions([1, 1, 1, 1, 1]) # 52
print good_partitions([2, 1]) # 4
print good_partitions([13, 11, 8]) # 29811734589499214658370837
它的測試案例產生正確的價值觀。我還用一個蠻力解決方案(對於小數值)測試了它,並且它產生了相同的結果。
以及你在那裏也問過它並得到了你的答案國際海事組織你可以在這裏關閉 – Carsten
由於表達式中的一些非線性因素,生成函數非常難以應用。獲得它的洞察力非常好,它告訴我們關於這個問題的一些事情。然而,不是,我正在尋找的確切數字。 – Azizi
[This](http://math.stackexchange.com/a/25516/66856)討論了生成函數的好處。實際上獲得數字需要一個聰明的算法(或可笑的計算能力)。 – Azizi