Задание №23 — Поиск количества программ
Исполнитель преобразует число на экране. У исполнителя есть три команды, которые обозначены латинскими буквами:
A. Прибавить 1
B. Умножить на 2
C. Возвести в квадрат
Программа для исполнителя – это последовательность команд. Сколько существует программ, для которых при исходном числе 2 результатом является число 20, при этом траектория вычислений не содержит числа 11? Траектория вычислений программы – это последовательность результатов выполнения всех команд программы.
Например, для программы CBA при исходном числе 4 траектория будет состоять из чисел 16, 32, 33.
Правильный ответ
37
Пояснение
Решение:
Все три команды строго увеличивают число (при исходном числе 2 прибавление единицы, удвоение и возведение в квадрат дают большее число), поэтому траектория растёт и «перепрыгнуть» цель, а потом вернуться к ней невозможно. Значит, количество программ удобно считать рекурсивно с конца.
Обозначим через число программ, переводящих в 20 так, чтобы дальше по траектории не встретилось 11. Тогда (пустая программа), при (цель проскочена) и — запрещённое число обнуляет весь путь, ведь если траектория попала в 11, программа уже не годится. В остальных случаях первый шаг делается одной из трёх команд, и варианты складываются: .
Считая от больших чисел к меньшим (или просто с кэшированием), получаем . Запрет на 11 существенно режет перебор: например, ветка полностью отбрасывается, и из 10 в 20 остаётся только удвоение.
from functools import lru_cache
@lru_cache(None)
def R(a):
if a == 11 or a > 20:
return 0
if a == 20:
return 1
return R(a + 1) + R(2 * a) + R(a * a)
print(R(2)) # 37
Ответ: 37