23.08 Прочие прототипы
Ошибка.
Попробуйте повторить позже
Исполнитель преобразует число на экране. У исполнителя есть пять команд, которым присвоены номера:
1. Увеличь на разряд единиц
2. Увеличь на разряд десятков
3. Умножь на разряд единиц
4. Умножь на разряд десятков
5. Прибавь 1
Первая и третья команды используют значение разряда единиц числа (например у 13 это 3, а у 28 - 8), а вторая и четвертая команды используют значение разряда десятков числа (например у 81 это 8, а у 35 это 3). Причём не разрешается выполнять команду, если после неё число на экране не изменится, либо превратится в 0. Программа для исполнителя – это последовательность команд.
Сколько существует программ, для которых при исходном числе 25 результатом является число 111, если известно, что нельзя повторять команду, сделанную два шага назад (например программа 112 допустима, а 121 - нет)?
Решение рекурсией
Мы будем использовать рекурсивный метод для подсчета всех допустимых программ. Введем функцию f(a, b, c1, c2), где:
- — текущее число на экране,
- — целевое число,
- — номер команды, использованной на предыдущем шаге,
- — номер команды, использованной два шага назад.
На каждом шаге проверяем условия:
- если , дальнейшее выполнение команд невозможно, возвращаем
;
- если , значит достигнут результат, возвращаем
.
Далее вычисляем единицы и десятки числа :
- — цифра единиц,
- — цифра десятков.
Для каждой команды проверяем:
- Если команда не была выполнена два шага назад (c2 != номер команды) и применение команды изменит число и
не приведет к 0, то рекурсивно вызываем функцию с новым значением числа и обновленными и
.
- Суммируем результаты всех возможных рекурсивных вызовов.
Функция кешируется с помощью lru_cache, чтобы ускорить вычисления за счет запоминания ранее вычисленных значений. Вызов f(25, 111) вернет количество всех допустимых программ.
# Импортируем кеширование для ускорения рекурсии from functools import lru_cache # Определяем рекурсивную функцию f(a, b, c1, c2) # a - текущее число, b - целевое число # c1 - предыдущая команда, c2 - команда два шага назад @lru_cache(None) def f(a, b, c1 = 0, c2 = 0): # Если текущее число больше целевого, путь невозможен if a > b: return 0 # Если текущее число равно целевому, найден допустимый путь if a == b: return 1 # Инициализируем счетчик программ на этом шаге s = 0 # Определяем цифру единиц числа a x = a % 10 # Определяем цифру десятков числа a y = a // 10 % 10 # Команда 1: прибавить разряд единиц if c2 != 1 and x != 0: s += f(a + x, b, 1, c1) # Команда 2: прибавить разряд десятков if c2 != 2 and y != 0: s += f(a + y, b, 2, c1) # Команда 3: умножить на разряд единиц if c2 != 3 and x != 0 and x != 1: s += f(a * x, b, 3, c1) # Команда 4: умножить на разряд десятков if c2 != 4 and y != 0 and y != 1: s += f(a * y, b, 4, c1) # Команда 5: прибавить 1 if c2 != 5: s += f(a + 1, b, 5, c1) # Возвращаем суммарное количество программ с этого шага return s # Вычисляем и выводим количество программ от 25 до 111 print(f(25, 111))
Специальные программы

Программа
лояльности v2.0
Приглашай друзей в Школково и получай вознаграждение до 10%!

Крути рулетку
и выигрывай призы!
Крути рулетку и покупай курсы со скидкой, которая привязывается к вашему аккаунту.

Бесплатное онлайн-обучение
Для школьников из приграничных территорий России, проживающих в ДНР, ЛНР, Херсонской, Запорожской, Белгородской, Курской, Брянской областях и Крыму.

Налоговые вычеты
Узнай, как получить налоговый вычет при оплате обучения в «Школково».

Специальное предложение
для учителей
Бесплатный доступ к любому курсу подготовки к ЕГЭ, ОГЭ и олимпиадам от «Школково». Мы с вами делаем общее и важное дело, а потому для нас очень значимо быть чем-то полезными для учителей по всей России!

Вернём деньги за курс
за твою сотку на ЕГЭ
Сдать экзамен на сотку и получить обратно деньги за подготовку теперь вполне реально!