23.04 Количество программ из A в B где траектория вычислений НЕ содержит число(-а)
Готовиться с нами - ЛЕГКО!
Ошибка.
Попробуйте повторить позже
Исполнитель Обычный преобразует число на экране. У исполнителя есть две команды, которым присвоены номера:
1. Прибавить 1
2. Умножить на 3
Программа для исполнителя Обычный – это последовательность команд. Сколько существует программ, для которых при исходном числе 3 результатом является число 36, и при этом траектория вычислений не содержит число 24?
Решение рекурсией
Мы решаем задачу рекурсивно, определяя функцию f(n, m), которая подсчитывает количество программ,
преобразующих число в число
. Идея состоит в том, чтобы на каждом шаге проверять текущую позицию и
принимать решение:
1. Если текущее число совпадает с целевым
, то найден корректный путь, и функция возвращает
.
2. Если текущее число больше
или равно запрещённому числу 24, путь невозможен, возвращаем
.
3. В остальных случаях мы применяем все возможные команды:
- n + 1, что соответствует команде «прибавить 1»;
- n * 3, что соответствует команде «умножить на 3»;
После чего суммируем результаты рекурсивных вызовов для этих двух вариантов.
Таким образом, вызов функции f(3, 36) рекурсивно переберёт все допустимые последовательности команд и вернёт общее количество программ.
# Определяем функцию f(n, m) для подсчета количества программ def f(n, m): # Если текущее число совпало с целевым, # значит найден корректный путь, возвращаем 1 if n == m: return 1 # Если текущее число стало больше целевого или равно запрещённому числу 24, # путь невозможен, возвращаем 0 if n > m or n == 24: return 0 # В остальных случаях считаем все возможные варианты: # применяем команду +1 и команду *3, складываем количество путей return f(n+1, m) + f(n*3, m) # Запускаем функцию от 3 до 36 и выводим результат print(f(3, 36))
—
Решение динамикой
Мы можем решить задачу динамически, создав массив a, где индекс соответствует числу, а значение по этому индексу — количество программ, которые приводят к этому числу.
1. Сначала создаём массив длиной 37 (чтобы включить число 36), все элементы равны 0.
2. В ячейку с индексом 3 записываем 1, так как стартуем с числа 3 и существует ровно один способ быть в этом положении.
3. Перебираем числа от 4 до 36. Для каждого числа :
- Добавляем количество способов из , так как можно прийти командой «прибавить 1»;
- Если делится на 3, то добавляем количество способов из
, так как можно прийти командой «умножить на
3»;
- Если равно 24, обнуляем значение, так как траектория не должна содержать это число.
В результате, значение a[36] будет содержать количество всех программ, которые из числа 3 приводят к числу 36 без прохождения через 24.
# Создаем массив для хранения количества программ до каждого числа a = [0] * 37 # Исходное число 3: только один способ быть в этом положении a[3] = 1 # Перебираем числа от 4 до 36 for i in range(4, 37): # Количество программ, ведущих в i, равно сумме: # 1) способов прийти из i-1 командой +1 # 2) способов прийти из i//3 командой *3, если i делится на 3 a[i] = a[i - 1] + a[i // 3] * (i % 3 == 0) # Пропускаем запрещённое число 24, обнуляем количество программ a[24] = 0 # Выводим количество программ, ведущих от 3 к 36 print(a[36])
Ошибка.
Попробуйте повторить позже
Исполнитель преобразует число на экране. У исполнителя есть две команды, которым присвоены номера:
1. Прибавить 1
2. Сделай нечётное
Выполняя первую команду, исполнитель увеличивает число на 1, а выполняя вторую – из числа x получает число 2x+1. Сколько существует программ, для которых при исходном числе 1 результатом является число 25 и при этом траектория вычислений не содержит число 21?
Решение рекурсией
Мы используем рекурсивный метод для подсчета всех программ, которые приводят от числа 1 к числу 25, избегая
числа 21. Для этого мы определяем функцию f(n, m), которая возвращает количество таких программ. Основная
логика функции строится на проверках текущего числа относительно целевого числа
и запрещённого числа
21:
1. Сначала проверяем, равно ли текущее число целевому
.
- Если , значит мы нашли корректный путь, поэтому возвращаем 1.
2. Затем проверяем, превысило ли текущее число целевое
или равно запрещённому числу 21.
- Если или
, путь невозможен, возвращаем 0.
3. Если ни одно из этих условий не выполнено, мы рассматриваем два возможных действия, которые может выполнить исполнитель:
- Выполнить команду "прибавить 1 что соответствует рекурсивному вызову f(n+1, m).
- Выполнить команду "сделай нечётное что соответствует рекурсивному вызову f(n*2 + 1, m).
Мы складываем результаты этих двух рекурсивных вызовов, чтобы получить общее количество программ для
текущего числа . Начальный вызов функции f(1, 25) перебирает все возможные последовательности команд от 1 до
25, соблюдая условие исключения числа 21.
# Определяем рекурсивную функцию f(n, m) для подсчета количества программ def f(n, m): # Если текущее число совпало с целевым, возвращаем 1 if n == m: return 1 # Если текущее число больше целевого или равно запрещенному числу 21, возвращаем 0 if n > m or n == 21: return 0 # В остальных случаях считаем количество программ, # выполняя каждую из двух возможных команд и суммируя результаты return f(n+1, m) + f(n*2 + 1, m) # Запускаем функцию с начальными числами 1 и 25 и выводим результат print(f(1, 25))
Ошибка.
Попробуйте повторить позже
Исполнитель Год23 преобразует число на экране. У исполнителя есть три команды, которым присвоены номера:
1. Прибавить 1
2. Прибавить 2
3. Умножить на 3
Сколько существует программ, для которых при исходном числе 3 результатом является число 40 и при этом траектория вычислений не содержит число 12?
Решение рекурсией
Мы используем рекурсивный подход для подсчёта количества программ. Сначала определяем функцию f(a, b),
которая считает, сколько существует программ, преобразующих число в число
с учётом всех условий. Внутри
функции проверяем следующие условия:
1. Если текущее число больше целевого числа
или равно запрещённому числу 12, то путь невозможен и
возвращаем 0.
2. Если текущее число совпадает с
, значит мы нашли корректную программу и возвращаем
1.
3. В противном случае считаем все возможные переходы: прибавляем 1, прибавляем 2 или умножаем на 3, вызывая функцию рекурсивно для каждого из вариантов и суммируя результаты.
Таким образом, каждая рекурсивная ветка проверяет корректность траектории и суммирует количество программ для всех допустимых вариантов. Вызов f(3,40) даст итоговое количество программ, которые из числа 3 приводят к числу 40, обходя число 12.
# Импортируем кэш для ускорения рекурсии from functools import lru_cache # Применяем кэширование для функции f @lru_cache(None) def f(a, b): # Если текущее число больше целевого или равно запрещённому 12 # путь невозможен, возвращаем 0 if a > b or a == 12: return 0 # Если текущее число совпало с целевым числом # найден корректный путь, возвращаем 1 if a == b: return 1 # В остальных случаях считаем все возможные переходы: # прибавить 1, прибавить 2, умножить на 3 return f(a + 1, b) + f(a + 2, b) + f(a * 3, b) # Вызываем функцию от 3 до 40 и выводим результат print(f(3,40))
—
Решение динамикой
Мы используем динамический способ, создавая массив a длиной 41, где индекс соответствует числу на экране, а значение по индексу показывает количество программ, ведущих к этому числу. Изначально заполняем массив нулями, а в ячейку с индексом 3 записываем 1, так как начинаем с числа 3.
Далее для каждого числа от 4 до 40 включительно выполняем следующие действия:
- Считаем количество программ, которые приходят к из
командой "прибавить 1".
- Считаем количество программ, которые приходят к из
командой "прибавить 2".
- Если делится на 3, считаем количество программ, которые приходят к
из
командой "умножить на
3".
- Если равно 12, принудительно обнуляем количество программ, так как число 12 запрещено в
траектории.
После прохода по всем индексам в массиве, итоговое количество программ хранится в a[40].
# Создаем массив из 41 элемента, все значения равны 0 a = [0] * 41 # В ячейку с индексом 3 записываем 1, так как стартуем с числа 3 a[3] = 1 # Перебираем все числа от 4 до 40 for i in range(4, 41): # Считаем количество программ из i-1, i-2 и i//3 a[i] = a[i - 1] + a[i - 2] + a[i // 3] * (i % 3 == 0) # Если число равно 12, обнуляем количество программ a[12] = 0 # Выводим количество программ, которые ведут от 3 к 40 без числа 12 print(a[40])
Ошибка.
Попробуйте повторить позже
Исполнитель преобразует число на экране.
У исполнителя есть две команды, которые обозначены латинскими буквами:
A. Прибавить 1
B. Умножить на 2
С. Возвести в квадрат
Сколько существует программ, для которых при исходном числе 2 результатом является число 20, при этом траектория вычислений не содержит числа 11? Траектория вычислений программы – это последовательность результатов выполнения всех команд программы. Например, для программы CBA при исходном числе 4 траектория будет состоять из чисел 16, 32, 33.
Для подсчёта количества программ используем рекурсивную функцию. Аргументы функции обозначают
количество способов преобразовать число
в число
при заданных правилах. Если
или в процессе получено
число
, то таких путей нет. Если
, найден один способ. Иначе программа может продолжиться тремя
командами:
,
или
. Таким образом,
+ f(a**2, b). Общее количество
программ результату вызова функции при
и
.
# Рекурсивная функция для подсчета количества программ def f(a, b): # Если текущее число больше целевого или равно 11 — пути нет if a > b or a == 11: return 0 # Если достигли целевого числа, найден один путь if a == b: return 1 # Иначе продолжаем тремя возможными командами: # A: a + 1, B: a * 2 return f(a + 1, b) + f(a * 2, b) + f(a ** 2, b) # Количество программ от 1 до 35 через 10, без числа 17 print(f(2, 20))