def c(n, k):
t = min(n - k, k)
n_fact = [n-i for i in range(t)]
for i in range(t):
for j in range(len(n_fact)):
if n_fact[j] % (i + 1) == 0:
n_fact[j] = n_fact[j] // (i + 1)
break
result = 1
for j in range(len(n_fact)):
result *= n_fact[j]
return result
print(c(500, 1))
print(c(500, 5))
print(c(500, 10))
Разбие́ние мно́жества — это представление его в виде объединения произвольного количества попарно непересекающихся подмножеств.
Выбираем опорный элемент, например {a} и находим все возможные тройки с этим элементом: abc,abd,abe,abf,acd,ace,acf,ade,adf,aef - всего 10 троек.
Теперь для каждого подмножества находим количество разбиений из оставшихся 3 элементов.
Например для тройки abc имеем такие варианты:
Вариант 1- def - и всё!
Т.е. всего имеем 10 исходных троек умноженное на 1 разбиение для каждого, равно 10 возможных разбиений.
Что ни разу не есть C(6,3) = 20
{{abc}, {def}} == {{def}, {abc}}
{abc} == {acb} == ... == {cba}
ab cd ef
ab ce df
ab cf de
ac bd ef
ac be df
ac bf de
ad bc ef
ad be cf
ad bf ce
ae bc df
ae bd cf
ae bf cd
af bc de
af bd ce
af be cd
abc def
abd cef
abe cdf
abf cde
acd bef
ace bdf
acf bde
ade bcf
adf bce
aef bcd
from math import factorial as f
def partition(n, steps):
def merge(aa, bb):
cc = {}
for i, a in aa.items():
for j, b in bb.items():
k = i + j
if k <= n:
cc[k] = cc.get(k, 0) + a // b
return cc
res = {0: f(n)}
for step in steps:
res = merge(res, {i * step: f(step) ** i * f(i) for i in range(n // step + 1)})
return res.get(n, 0)
print(partition(6, [2])) # 15, как и ожидалось
print(partition(6, [3])) # 10 -//-
print(partition(6, [2, 3])) # 25 - тут простая сумма, так как
# в разбиении либо только пары, либо только тройки
print(partition(5, [2, 3])) # 10 - тут как раз биноминальный коэфф,
# так как делим на 2 и 3 буквы
print(partition(7, [2, 3])) # 105 - тут возможно лишь разбиение 3+2+2
print(partition(10, [1, 5, 10])) # 380