Задание №23 — Поиск количества программ
Исполнитель преобразует число на экране. У исполнителя есть две команды, которым обозначены латинскими буквами:
1) Вычти 1
2) Найди целую часть от деления на 2
Первая из них уменьшает число на экране на 1, вторая заменяет число на экране на число, равное целой части от деления числа на экране на 2. Программа для исполнителя — это последовательность команд. Сколько существует программ, которые преобразуют исходное число 31 в число 2, причём траектория вычислений программы содержит число 12? Траектория вычислений программы — это последовательность результатов выполнения всех команд программы.
Например, для программы ABA при исходном числе 18 траектория будет состоять из чисел 17, 8, 7.
Правильный ответ
171
Пояснение
Решение:
Обе команды только уменьшают число на экране, поэтому траектория строго убывает и одно и то же число не может встретиться в ней дважды. Значит, каждая подходящая программа однозначно разбивается на две независимые части: сначала число превращается в , затем превращается в . По правилу умножения искомое количество равно произведению количеств программ для этих двух участков.
Пусть — количество программ, переводящих в . Если , подходит только пустая программа, то есть ; если , то — увеличивать число команды не умеют. Иначе первая команда переводит либо в , либо в , поэтому
from functools import lru_cache
@lru_cache(None)
def f(x, y): # сколько программ переводят число x в число y
if x == y:
return 1 # пустая программа
if x < y:
return 0 # число стало меньше нужного - обратно уже не вернуть
return f(x - 1, y) + f(x // 2, y)
print(f(31, 12) * f(12, 2))
Получаем и , то есть всего программ.
Ответ: 171