Ещё о разбиениях.
В OEIS есть последовательность,
A000041 -- количество разбиений числа на слагаемые.
Там написана куча всего, и что это не только количество разбиений но и то и сё и пятое и десятое... Большая, можно сказать, статья.
Там есть и несколько способов расчета количества разбиений, в т.ч. через производящие функции как нравится ув.
arseniiv, и рекурсивные способы и другие.
в
PARI/GP есть специальные функции которые считают количество разбиений, например для варианта a) задачи им.
Yadryara (разложить непомеченные шары в непомеченные урны не менее одного шара в урну) есть функция посчета
numbpart, работает она так:
? numbpart(7)
%1 = 15Это общее количество разбиений числа 7 на слагемые.
Есть также генератор разбиений, функция
partitions, которая выдаёт все разбиения, или только соответствующие ограничениям.
Для нашего случая работает так
? partitions(7,,[3,3])
%1 = [Vecsmall([1, 1, 5]), Vecsmall([1, 2, 4]), Vecsmall([1, 3, 3]), Vecsmall([2, 2, 3])]Выдает разбиения числа
7 на не менее
3 и не более
3 частей (т.е. ровно на три части).
В PARI/GP есть оператор # который выдает количество элементов массива, вектора и т.п., так что количество по варианту а) задачи считается так:
? #partitions(7,,[3,3])
%1 = 4То есть таких разбиений 4.
Дальше можно пользоваться этим результатом и по каждому из 4 разбиений посчитать количество вариантов.
Обозначения:
Представим разбиение числа на слагаемые шаров на урны (
шаров по
урнам) в новых обозначениях так
и
То есть
- это сколько шаров в урне, а
- это сколько таких урн, при том что
не повторяются (все
различны)
Например для расклада 223
Формула:
Для облегчения итерирования по разбиениям, в PARI/GP есть оператор
forpart, которые пербирает все разбиения удовлетворяющие условию. На нашего варианта а) он работает так:
? forpart(v=7,print(v),,[3,3])
Vecsmall([1, 1, 5])
Vecsmall([1, 2, 4])
Vecsmall([1, 3, 3])
Vecsmall([2, 2, 3])Соответственно, вместо
print(v) можем вставить обработку конкретного разбиения (которое помещается в вектор
v) - подсчет количества вариантов, накопление суммы.
Если надо только проверить правильно ли считается количество, то в
PARI/GP есть специальные функции которые прямо вычисляют все варианты. Так что для всех наших вариантов
ответы получаем прямо вот так, не мудрствуя лукаво:
? variant_a(n,m)=#partitions(n,,[m,m]);
? variant_a(7,3)
%1 = 4? variant_b(n,m)=binomial(n-1,m-1);
? variant_b(7,3)
%1 = 15? variant_v(n,m)=stirling(n,m,2);
? variant_v(7,3)
%1 = 301? variant_g(n,m)=m!*stirling(n,m,2);
? variant_g(7,3)
%1 = 1806Для чего я это написал: я всё ещё думаю что
romzes200677 надо
написать и отладить программы для расчета вариантов
а-г, а чтобы не сверяться все время с форумом, пользоваться короткими функциями которые уже есть в матпакетах, в том же
PARI/GPИ освоить не только задачи
а-г, но освоить
всё "двенадцатизадачие", сформулированное в книжке Кнута (4 Том "Искусства программирования", раздел 7.2.1.4):