Задано целевое значение N и массив допустимых положительных чисел. Необходимо определить количество способов представить N в виде суммы из этих чисел.
Например, если в качестве допустимых значений взять [1, 2, 3], а число N равно 4, то существует 7 разных способов сложить эти числа, чтобы получить 4:
Все 7 способов сложить 1, 2, 3, чтобы получить 4
1 + 1 + 1 + 1
1 + 1 + 2
1 + 2 + 1
2 + 1 + 1
1 + 3
3 + 1
2 + 2
Это классическая задача динамического программирования, которую можно решить путём хранения состояния d[sum], отражающего все возможные способы получить сумму sum из разрешённых чисел:
N = ...
nums = [...]
d = [0] * (N + 1) # d[i] = все комбинации, которые в сумме дают i
d[0] = 1 # Существует 1 способ получить 0 – не брать ни одного числа
for i in range(1, N + 1): # Пытаемся вычислить d[i] последовательно для i от 1 до N
for num in nums: # Пробуем получить d[i] с помощью num
if i - num >= 0: # Проверяем, возможно ли сформировать i из num
d[i] += d[i - num]
print(d[N])
Таким образом, наше состояние d[i] — это количество способов получить i, используя допустимые числа из nums. Изначально все значения обнуляются, кроме d[0], которое выставляется равным 1, поскольку мы можем получить 0 единственным способом — не используя ни одного числа. Для всех остальных чисел мы последовательно перебираем все разрешённые варианты из nums.
Если, к примеру, мы можем получить число 11 (d[11]) 5 разными способами и знаем, что число 8 (d[8]) мы могли получить 3 разными способами, то при наличии в nums числа 3 мы можем сформировать 11 всеми найденными ранее способами плюс всеми способами получения 8 (d[8]), добавив в конце число 3.
Давайте прогоним алгоритм на примере:
nums = [1, 2, 3] и N = 4
d = [1, 0, 0, 0, 0] → 1 способ получить 0, остальные пока равны 0
i = 1
num = 1 ⇒ d[1] += d[0] ⇒ d = [1, 1, 0, 0, 0]
num = 2 ⇒ i - num < 0
num = 3 ⇒ i - num < 0
i = 2
num = 1 ⇒ d[2] += d[1] ⇒ d = [1, 1, 1, 0, 0]
num = 2 ⇒ d[2] += d[0] ⇒ d = [1, 1, 2, 0, 0]
num = 3 ⇒ i - num < 0
i = 3
num = 1 ⇒ d[3] += d[2] ⇒ d = [1, 1, 2, 2, 0]
num = 2 ⇒ d[3] += d[1] ⇒ d = [1, 1, 2, 3, 0]
num = 3 ⇒ d[3] += d[0] ⇒ d = [1, 1, 2, 4, 0]
i = 4
num = 1 ⇒ d[4] += d[3] ⇒ d = [1, 1, 2, 4, 4]
num = 2 ⇒ d[4] += d[2] ⇒ d = [1, 1, 2, 4, 6]
num = 3 ⇒ d[4] += d[1] ⇒ d = [1, 1, 2, 4, 7]
print(d[4]) → выводит 7
Задание – Комбинации с кубиком (Dice Combinations)
Если вы бросаете игральную кость, она может выдать число от 1 до 6. Нужно вычислить, сколькими способами можно получить число n, суммируя результаты бросков.
Входные данные
Во входных данных дано одно целое число n (1 ≤ n ≤ ).
Выходные данные
Программа должна вывести количество способов, которыми можно набрать сумму n, последовательно бросая кость. Поскольку ответ может быть очень большим, нужно напечатать его по модулю .