Тема 23. Оператор присваивания и ветвления

23.05 Количество программ из A в B смешанное

Вспоминай формулы по каждой теме
Решай новые задачи каждый день
Вдумчиво разбирай решения
ШКОЛКОВО.
Готовиться с нами - ЛЕГКО!
Подтемы раздела оператор присваивания и ветвления
Решаем задачу:

Ошибка.
Попробуйте повторить позже

Задача 1#72447

Исполнитель Год23 преобразует число на экране. У исполнителя есть две команды, которым присвоены номера:

1. Прибавить 1

2. Умножить на 2

Сколько существует программ, для которых при исходном числе 8 результатом является число 36 и при этом траектория вычислений содержит число 5 и не содержит число 20?

Показать ответ и решение

Решение руками:

Заметим, что исходная число по условию 8. Команд, которые уменьшают число нет. По условию программа должна пройти через число 5. Мы никак не можем попасть в число 5, так как 8 никак нельзя уменьшить, следовательно, таких программ нет и ответ тогда 0.

Решение рекурсией

Мы используем рекурсивный способ решения задачи, так как можем рассматривать каждую программу как последовательность команд, которые приводят к целевому числу. Для этого создаем функцию f(a, b), которая возвращает количество программ, преобразующих число a в число b. Внутри функции мы выполняем следующие шаги:

1. Проверяем, если текущее число a стало больше b или равно запрещённому числу 20, то такая траектория невозможна, возвращаем 0.

2. Проверяем, если a равно b, значит найден один корректный путь, возвращаем 1.

3. В остальных случаях рекурсивно вызываем функцию дважды:

- один раз с аргументом a+1, что соответствует команде "прибавить 1";

- второй раз с аргументом a*2, что соответствует команде "умножить на 2".

Суммируем результаты этих двух вызовов, чтобы получить общее количество программ для текущего состояния.

Так как условие требует, чтобы траектория проходила через число 5 и не содержала число 20, мы делим решение на два этапа: от 8 до 5 и от 5 до 36. Произведение f(8, 5) * f(5, 36) даст окончательное количество программ, удовлетворяющих всем условиям.

# Определяем рекурсивную функцию f(a, b) для подсчета программ
def f(a, b):
    # Если текущее число стало больше целевого или равно запрещённому числу 20,
    # путь невозможен, возвращаем 0
    if a > b or a == 20:
        return 0
    # Если текущее число совпало с целевым,
    # найден корректный путь, возвращаем 1
    if a == b:
        return 1
    # В остальных случаях считаем все возможные варианты переходов:
    # прибавление 1 и умножение на 2, и складываем результаты
    return f(a + 1, b) + f(a * 2, b)

# Вычисляем общее количество программ, проходящих через число 5 и не содержащих 20
print(f(8, 5) * f(5, 36))

Решение динамикой

Мы можем решить задачу динамическим способом, создавая массивы для хранения количества программ для каждого числа на траектории. Разделяем задачу на два этапа: от 8 до 5 и от 5 до 36.

1. Первый этап: от 8 до 5

- Создаем массив a длиной 37 (чтобы включить число 36).

- Записываем a[8] = 1, так как начальное число — 8, существует один способ быть в этом положении.

- Проходим по всем индексам от 9 до 5 включительно:

      - Если число чётное, можем прийти либо командой "+1"из i-1, либо командой "*2"из i//2; суммируем эти значения в a[i].

      - Если число нечётное, можем прийти только командой "+1 добавляем a[i-1].

2. Второй этап: от 5 до 36

- Создаем массив b длиной 37.

- Записываем b[5] = 1, начальное число 5.

- Проходим по всем индексам от 6 до 36 включительно:

      - Пропускаем число 20, так как траектория не должна его содержать.

      - Для чётных чисел добавляем суммы из b[i-1] и b[i//2].

      - Для нечётных чисел добавляем только b[i-1].

Общее количество программ равно произведению a[5] * b[36], так как каждый путь из первой части можно соединить с любым путем из второй части.

# Первый этап: от 8 до 5
a = [0] * (36 + 1)  # Создаем массив для чисел до 36 включительно
a[8] = 1  # Начальное положение — число 8
# Перебираем числа от 9 до 5 включительно
for i in range(9, 5 + 1):
    # Если число чётное, учитываем команды +1 и *2
    if i % 2 == 0:
        a[i] = a[i - 1] + a[i // 2]
    else:
        # Если число нечётное, учитываем только команду +1
        a[i] = a[i - 1]

# Второй этап: от 5 до 36
b = [0] * (36 + 1)  # Создаем массив для чисел до 36 включительно
b[5] = 1  # Начальное положение — число 5
# Перебираем числа от 6 до 36 включительно
for i in range(6, 36 + 1):
    # Пропускаем число 20, так как оно запрещено
    if i == 20:
        continue
    # Если число чётное, учитываем команды +1 и *2
    if i % 2 == 0:
        b[i] = b[i - 1] + b[i // 2]
    else:
        # Если число нечётное, учитываем только команду +1
        b[i] = b[i - 1]

# Выводим итоговое количество программ
print(a[5] * b[36])

Ответ: 0

Специальные программы

Все специальные программы

Программа
лояльности v2.0

Приглашай друзей в Школково и получай вознаграждение до 10%!

Крути рулетку
и выигрывай призы!

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

Бесплатное онлайн-обучение

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

Налоговые вычеты

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

Специальное предложение
для учителей

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

Вернём деньги за курс
за твою сотку на ЕГЭ

Сдать экзамен на сотку и получить обратно деньги за подготовку теперь вполне реально!

cyberpunkMouse
cyberpunkMouse
Рулетка
Вы можете получить скидку в рулетке!