Задание 13
Анализ хода исполнения алгоритма
Как посчитать программы исполнителя, не выписывая их: дерево, таблица и программа на Python — с обязательными и запрещёнными числами и разными командами.
7 подтем · 43 задачи + 11 дополнительных · повышенный · ≈ 7 мин
Подтема 1 из 7
Команды, программы и дерево
Что такое программа и траектория, как перебрать все программы деревом и почему его можно сократить.
Как устроена тема
В задании 13 исполнитель меняет число своими командами, а спрашивают, сколько разных программ ведут от одного числа к другому. Вот задача, которую мы будем решать всю тему:
«Исполнитель преобразует число на экране. У исполнителя есть две команды, которым присвоены номера: 1. Прибавить 1; 2. Умножить на 2. Программа для исполнителя — это последовательность команд. Сколько существует программ, для которых при исходном числе 2 результатом является число 20, и при этом траектория вычислений содержит число 6 и не содержит числа 9? Траектория вычислений программы — это последовательность результатов выполнения всех команд программы.»
Выписывать все программы долго — их много, и они длинные. Мы научимся считать их, не выписывая. Сначала разберём, что сказано в условии:
| В условии | Что это значит |
|---|---|
| команды 1 и 2 | 1 — прибавить 1, 2 — умножить на 2; программу пишут номерами: 121 — это «прибавить, умножить, прибавить» |
| исходное число 2, результат 20 | начинаем с 2, после последней команды на экране 20 |
| траектория | числа на экране после каждой команды |
| содержит 6 | 6 хотя бы раз появилось на экране |
| не содержит 9 | 9 не появилось ни разу |
| сколько существует программ | посчитать все подходящие программы |
Тема состоит из семи подтем — у каждой своя страница. Идём по ним по порядку:
- Команды, программы и дерево — ты сейчас здесь.
- Таблица количества программ — тот же счёт без дерева для участка из 6 в 20.
- Обязательные и запрещённые числа — обязательное 6, запрещённое 9 и ответ задачи.
- Новые и условные команды — другие команды вместо «+1» и «×2».
- Убывание и деление — команды, которые уменьшают число.
- Группы программ и обратные вопросы — дополнительный урок для редких условий.
- Длина и память программы — ещё один дополнительный урок.
Почти везде задачу можно решить и вручную, и программой — выбирай вкладку «Вручную» или «Python». На экзамене подойдёт любой способ, а второй пригодится для проверки.
Программа и траектория
Возьмём исходное число 3 и выполним две программы: 12 и 21.
Программа — последовательность команд, записанная их номерами. Команды выполняют слева направо, по одной. Программа 12: сначала команда 1 — 3 + 1 = 4, потом команда 2 — 4 · 2 = 8. Программа 21 — те же команды в другом порядке: 3 · 2 = 6, потом 6 + 1 = 7.
Траектория — числа, которые появились на экране после каждой команды: у программы 12 это 4 и 8, у программы 21 — 6 и 7. Исходное число 3 в траекторию не входит: его не получала ни одна команда.
Обрати внимание: считают программы, а не числа. Из 1 команда 1 даёт 1 + 1 = 2 и команда 2 даёт 1 · 2 = 2. Число одно, а программы две — 1 и 2. Поэтому из 1 в 4 ведут четыре программы: 111, 12, 21 и 22.
Тонкости:длина и направление
Если длина не ограничена, считают программы любой длины, а не только самые короткие.
Команды «+1» и «×2» на положительных числах только увеличивают число: перешагнув цель, к ней уже не вернуться, поэтому программ конечное число. Но так бывает не всегда: из 0 умножение на 2 снова даёт 0, а квадрат из 1 — снова 1. Такую команду можно повторять сколько угодно раз, и программ становится бесконечно много.
Дерево вариантов
Сколько программ переводят 2 в 6 — первый участок задачи темы?
Дерево перебирает все программы: из каждого числа выходит по ветке на каждую команду. Строим его от 2:
- Из 2 команда 1 даёт 3, команда 2 — 4: две ветки.
- Из каждого нового числа снова пробуем обе команды.
- Получили 6 — ветка закончилась успехом: это одна программа.
- Получили больше 6 — ветку обрываем: команды только увеличивают число, к 6 уже не вернуться.
Слева идём через 3: дальше 3 → 4 → 5 → 6 — это программа 1111, а 3 · 2 = 6 — программа 12. Справа через 4: 4 → 5 → 6 — программа 211, а 4 · 2 = 8 уже больше 6. Успешных листьев три — значит, и программ три.
В коде дерево превращается в — функцию, которая вызывает сама себя для каждой ветки. Функцию f(x, y) задаём через , она считает программы из x в y. Каждая её строка с или return — одно правило дерева:
if x > y: return 0— ветка перепрыгнула цель, программ нет;if x == y: return 1— дошли до цели, это одна программа;f(x + 1, y) + f(x * 2, y)— две ветки, их программы складывают.
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(2, 6))Раскрутку одной ветки дерева — из 3 в 6 — пройди по шагам:
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(3, 6))Повторы в дереве
В дереве число 4 встретилось дважды: слева — после 2 → 3 → 4, справа — сразу после 2 → 4. Нужно ли продолжать его два раза?
Из одинаковых чисел дерево растёт одинаково, поэтому число достаточно записать один раз и отметить, сколькими программами в него пришли. В 4 пришли две программы (11 и 2), и каждую можно продолжить одинаково: 4 → 5 → 6. Значит, через 4 в 6 ведут две программы.
Это количество обозначают K(n): сколько программ переводят старт в число n. Запишем числа от 2 до 6 в строку, а под каждым — K:
Такая таблица заменяет дерево, когда чисел много, — ей посвящена подтема 2.
Итого
- Программапоследовательность команд
- Разные программыразный порядок команд, даже при одном результате
- Траекториячисла после команд, без старта
- Деревоветка на команду, обрыв за целью
- Повторычисло один раз, под ним K(n)
- Python
f(x + 1, y) + f(x * 2, y)
Проверьте себя
Ответь сначала сам, потом открой ответ.
ОтветСкрыть ответ
ОтветСкрыть ответ
ОтветСкрыть ответ
ОтветСкрыть ответ
ОтветСкрыть ответ
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Результат программы 121
Команда 1 прибавляет 1, команда 2 умножает на 2. Какое число получится из 3 после выполнения программы 121?
Введите число.
Подсказка
Выполняй команды по порядку: каждая работает с результатом предыдущей.
Решение
3 + 1 = 4, затем 4 · 2 = 8, затем 8 + 1 = 9. Траектория — 4, 8, 9: исходное число в неё не входит.
x = 3for c in '121': if c == '1': x = x + 1 else: x = x * 2print(x)Ответ: 9
Программы из 3 в 9
Команды «+1» и «×2». Сколько программ переводят 3 в 9?
Введите число.
Подсказка
Построй дерево: ветка на каждую команду, обрыв за целью.
Решение
Программ три: 111111, 121 (3 → 4 → 8 → 9) и 2111 (3 → 6 → 7 → 8 → 9). Другие ветки перепрыгивают 9: 8 · 2 = 16, 6 · 2 = 12.
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(3, 9))Ответ: 3
Программы из 3 в 10
Команды «+1» и «×2». Сколько программ переводят 3 в 10?
Введите число.
Подсказка
Удвоение больше 5 сразу перепрыгивает 10.
Решение
Программы: 1111111, 112 (3 → 4 → 5 → 10), 1211 (3 → 4 → 8 → 9 → 10) и 21111 (3 → 6 → 7 → … → 10) — четыре.
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(3, 10))Ответ: 4
Из 1 в 9: +1 и ×3
Исполнитель преобразует число на экране. У исполнителя есть две команды: 1. Прибавить 1; 2. Умножить на 3. Программа для исполнителя — это последовательность команд. Сколько существует программ, для которых при исходном числе 1 результатом является число 9?
Введите число.
Подсказка
Умножение на 3 возможно только из чисел до 3.
Решение
Программы: 11111111, 112 (1 → 2 → 3 → 9), 12111 (1 → 2 → 6 → … → 9), 2111111 (1 → 3 → 4 → … → 9) и 22 (1 → 3 → 9) — пять.
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 3, y) print(f(1, 9))Ответ: 5
Вывод f(2, 8)
Что выведет эта программа?
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(2, 8))Введите число.
Подсказка
f(x, y) — число программ из x в y командами «+1» и «×2».
Решение
Функция считает программы из 2 в 8 командами «+1» и «×2»: 111111, 112, 1211, 21111 и 22 — пять.
def f(x, y): if x > y: return 0 if x == y: return 1 return f(x + 1, y) + f(x * 2, y) print(f(2, 8))Ответ: 5