На мой взгляд, проблема состоит в том, чтобы найти количество отсортированных списков максимум из 90 элементов, сумма которых равна 90.
Существует концепция, которая довольно близка к этому, и мы называем это разделы числа.
Например, разделы 4: [4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]
.
После небольшого исследования я нашел эту статью , которая имеет отношение к Ваша проблема.
Как объясняется там, метод рекурсии приводит к очень длинному вычислению для больших чисел, , но ...
Гораздо эффективнее подход через подход, называемый Dynami c Программирование . Здесь мы вычисляем функцию psum (n, k), которая представляет собой общее количество n-разбиений с наибольшим компонентом k или меньше. На любом данном этапе мы вычислим значения psum (1, k), psum (2, k), psum (3, k), ..., psum (n, k) для некоторого фиксированного k. Учитывая этот вектор из n значений, мы вычисляем значения для k + 1 следующим образом:
psum (i, k + 1) = psum (i, k) + p (i, k ) для любого значения i
Но напомним, что p (i, k) = Σj p (ik, j) = psum (ik, k)
Итак, psum (i, k + 1) = psum (i, k) + psum (ik, k)
Таким образом, с небольшой осторожностью мы можем повторно использовать вектор значений и вычислить значения psum (i, k) в скользящем значении для последовательно больших значений k. Наконец, у нас есть вектор со значениями psum (i, n). Значение psum (n, n) является искомым значением p (n). В качестве дополнительного преимущества мы видим, что мы одновременно вычислили значения p (1), p (2), ..., p (n).
В основном, если вы сохраняете промежуточные значения В списке и использовать повторения, представленные в статье,
psum(i,k+1) = psum(i,k) + psum(i-k,k)
вы можете использовать следующую функцию:
def partitionp(n):
partpsum = [1] * (n + 1)
for i in range(2, n + 1):
for j in range(i, n + 1):
partpsum[j] += partpsum[j - i]
return partpsum[n]
На каждой итерации внешнего для l oop, список partpsum
содержит все значения psum (1, k), psum (2, k), psum (3, k), ..., psum (n, k). В конце итерации вам нужно только вернуть psum (n, n).