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

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

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

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

Задача 1#11542

Исполнитель АС преобразует число на экране.

У исполнителя есть три команды, которым присвоены номера:

  1. Прибавить 1  ;
  2. Умножить на 2  ;
  3. Умножить на 3  .

Первая команда увеличивает число на экране на 1  , вторая умножает его на 2  , третья умножает на 3  .

Программа для исполнителя АС — это последовательность команд. Сколько существует программ, которые преобразуют исходное число 1  в число 50  , и при этом траектория вычислений содержит число 14  и не содержит числа 16  ?

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

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

Мы решаем задачу рекурсивно, создавая функцию f(x, y), которая считает количество программ, преобразующих число x  в число y  . 1. Сначала проверяем, нарушает ли текущее число x  условие задачи: - Если x > y  , то дальнейшие преобразования уже не приведут к числу y  , поэтому возвращаем 0. - Если x = 16  , то траектория запрещена по условию задачи, возвращаем 0. 2. Проверяем, достигли ли мы цели: - Если x = y  , значит найден один корректный путь, возвращаем 1. 3. Если ни одно из условий не выполнено, считаем все возможные переходы из текущего числа: - Прибавляем 1 и вызываем f(x + 1, y) - Умножаем на 2 и вызываем f(x * 2, y) - Умножаем на 3 и вызываем f(x * 3, y) - Складываем результаты всех трёх вызовов, чтобы получить общее количество программ.

Так как по условию траектория должна содержать число 14, но не содержать число 16, мы делаем два независимых вызова функции: f(1, 14) и f(14, 50), а затем перемножаем результаты, так как каждый путь из первой части можно соединить с любым путем из второй части.

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

# Вычисляем количество программ от 1 до 14 и от 14 до 50
# и перемножаем результаты, так как траектория должна проходить через 14
print(f(1, 14) * f(14, 50))

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

Мы решаем задачу динамическим способом, создавая массив a длиной 51 (для чисел от 0 до 50), где a[i] хранит количество программ, которые преобразуют число 1 в число i  .

1. Инициализируем массив нулями: a = [0]*51 2. Задаём начальное положение: a[1] = 1, так как изначально мы находимся в числе 1. 3. Перебираем числа от 2 до 50: - Для каждого числа i добавляем количество программ, ведущих в i из i-1 (команда +1): a[i] = a[i-1] - Если i делится на 2, добавляем количество программ, ведущих в i из i//2 (команда *2): a[i] += a[i//2] - Если i делится на 3, добавляем количество программ, ведущих в i из i//3 (команда *3): a[i] += a[i//3] - Если i = 14, нужно сбросить все значения для чисел меньше 14, так как траектория до 14 должна быть из 1 без промежуточного попадания в запрещенные числа: for j in range(14): a[j] = 0 - Если i = 16, обнуляем a[i] по условию запрета на число 16: a[i] = 0

4. После прохода по всем числам a[50] содержит количество программ от 1 до 50 с учётом всех условий.

# Создаем массив для чисел от 0 до 50, изначально заполненный нулями
a = [0]*51
# Начальное положение — число 1
a[1] = 1
# Перебираем числа от 2 до 50 включительно
for i in range(2, 51):
    # Добавляем количество программ, ведущих из i-1
    a[i] = a[i-1]
    # Добавляем количество программ, ведущих из i//2, если возможно
    if i % 2 == 0:
        a[i] += a[i//2]
    # Добавляем количество программ, ведущих из i//3, если возможно
    if i % 3 == 0:
        a[i] += a[i//3]
    # Если достигли числа 14, обнуляем все числа меньше 14
    if i == 14:
        for j in range(14):
            a[j] = 0
    # Если число 16 запрещено, обнуляем его
    if i == 16:
        a[i] = 0

# Выводим количество программ, ведущих от 1 до 50 с учетом условий
print(a[50])

Ответ: 192

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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