Найти в Дзене
Репетитор IT mentor

Рекурсия и задача с исполнителем из ЕГЭ по информатике

Оглавление

Недавно разбирали с учеником 23 задачу из ЕГЭ по информатике. Хотел бы поделиться своими мыслями и некоторыми лайфхаками решения этой задачи с моими дорогими подписчиками. Очень надеюсь, что кому-нибудь эта заметка будет полезна или хотя бы интересна. Поэтому прошу не поскупиться на обратную связь, если эта тема интересна. Если же вам это не нравится, то можете поставить дизлайк — в вашей ленте будет меньше такой ерунды. А пока погнали начинать, сразу с практики :)

Задача [Тип 23] 

Исполнитель А16 преобразует число, записанное на экране. У исполнителя есть три команды, которым присвоены номера:
1.  Прибавить 1;
2.  Прибавить 2;
3.  Умножить на 2;
Первая из них увеличивает число на экране на 1, вторая увеличивает его на 2, третья умножает его на 2. Программа для исполнителя А16 – это последовательность команд.
Сколько существует таких программ, которые исходное число 3 преобразуют в число 12 и при этом траектория вычислений программы содержит число 10? Траектория вычислений программы  — это последовательность результатов выполнения всех команд программы. Например, для программы 132 при исходном числе 7 траектория будет состоять из чисел 8, 16, 18.

Решение:

Попытка нарисовать полное дерево — плохой способ. Давайте начнем рисовать. Уверяю вас, что мы быстро устанем в попытках изобразить все возможные ветки нашего дерева, на которых будут получаться числа 12. (и на самом деле дерево будет перекошено в одну сторону, т.к. умножение на 2 быстро будет выходить за пределы 12). И всё равно это очень много трудозатрат. Смотрите сами...

-2

Посмотреть картинку в исходном качестве

Как мы видим отсюда, тут невозможно полноценно построить все решения. Пока рисовал тот способ, то придумал более компактный. У нас всё равно ограниченное количество интересующих нас чисел. Так почему бы не выписать их все в строчку (или в круг, как вам нравится больше?), а затем расставить у всех весовые коэффициенты. Тогда весовой коэффициент последнего числа будет являться ответом на задачу. Сложно? Давайте я нарисую, сразу станет легке :)

-3

Здесь важно отметить, что:
1. Черными цифрами внутри кружков обозначаются числа, в которых мы находимся и которые мы получаем с помощью трех инструкций, которые способен сделать исполнитель.
2. Красные числа рядом - весовые коэффициенты. Весовой коэффициент исходной вершины графа (в нашем случае это 3) является равным 1, потому что у нас только 1 способ оказаться в этой вершине, ибо она исходная. Весовой коэффициент каждой новой вершины можно посчитать, суммируя весовые коэффициенты тех вершин графа, из которых идут стрелки в нашу текущую вершину, для которой в текущий момент времени мы считаем весовой коэффициент. Проще: сколько стрелок входит, столько весовых коэффициентов складываем для определения веса текущей вершины/точки/числа. Вот такой вот графический способ.

Второй способ решения задачи — аналитический. У нас есть некоторая функция Nₖ - количество возможных способо добраться в число k. И мы рекурсивно просчитываем эту функцию для каждого нужного числа. Начинать проще с конца. Показываю:

Количество способов получить 10 из 3

-4

Количество способов получить 12 из 10

-5

Зная количество ветвей/путей, ведущих в 10 из 3 и количество путей, ведущих в 12 из 10, мы можем получить количество способов попасть из 3 в 12, обязательно проходя через 10, просто перемножив полученные значения: 2×30 = 60. Обратите внимание, что именно такой весовой коэффициент получился у числа «12» на втором рисунке, где мы сделали оптимизированный граф (графическое решение задачи).

Есть и третий способ решения — оптимизация через программирование

Мы уже видели в аналитических расчетах рекурсивное поведение функции N, которая определяет количество способов. Также можно заметить, что мы передвигаемся по целым числам, поэтому:
1. Количество способов получить четное число на текущем шаге
→ 3 (пример: N(8) = N(7) + N(6) + N(4).)
2. Количество способов получить нечетное число на текущем шаге → 2 (пример: N(9) = N(8) + N(7).)

Вот такой будет код решения

-6

Стоит заметить, что это тоже не оптимизированное решение, потому что если попробовать взять относительно небольшие числа, например a = 3 и b = 40, то количество способов получить число 40 из 3 с помощью трех инструкций (+1, +2, *2) составляет 5 994 1014 ~ 6 миллионов возможных путей. И вот тут Python уже начинает заметно тормозить. Интересно, что выдала бы аналогичная программа на C/Assembler. Кто попробует переписать? :)

У нас действительно огромное количество рекурсивных вызовов, поэтому (возможно) оптимизировать можно было бы, если переписать решение через цикл или бить рекурсию на части, которые после запускать в разных потоков, чтобы добиться хоть какой-то псевдопараллельности выполнения.

Ссылка на код github

GitHub - HaloMath/Recursion-task-with-a-performer-from-the-Unified-State-Exam-: Recursion, a task with a performer from the Unified State Exam in computer science

Интересны разборы задач по программированию и информатике? Есть ещё...

Парсинг Excel-файлов на Python на примере задачи из ЕГЭ по информатике

17 задача ЕГЭ по информатике - анализ файлов .txt

7 задач по информатике и программированию из ЕГЭ: подробный разбор

Большой подвох в маленькой задаче на языке C

7 задача из ЕГЭ по информатике

Как перенести названия всех файлов текущей директории в текстовый файл .txt в Python?

Задача про лягушку и комаров

Написал свой калькулятор выхода на пенсию (FIRE)

Работа со StringGrid в Lazarus (Object Pascal)

Введение в работу со строками на языке программирования C

Задача про таблицу истинности из МЦКО по информатике

Новые задачки по Excel из ЕГЭ по информатике?

Как ускорить выполнение цикла? Алгоритм оптимизации циклов

Какая строка получится? Разбор 12 задачи из ЕГЭ по информатике

Работаем с файлами и строками в Pascal : на примере 24 задачи из ЕГЭ по информатике

Оптимизация поиска количества делителей | Ускоряем программу в 58 раз | Разбор ЕГЭ по информатике

Задание 25 из ЕГЭ по информатике: разбираемся с делителями

Разбор 26 задачи ЕГЭ по информатике: серьезный подвох

Что делать, если программирование кажется сложным, но очень хочется разобраться в нем? #3

Проблемы использования тригонометрических функций в программировании

Объекты в JavaScript: всё что нужно знать начинающему

8 хороших задач для начинающих: программируем на Python

Метод Якоби: решение СЛАУ методом итерации

Замыкания в Javascript на 3 простых примерах

Разбираем циклы в Python на простых примерах. Какой цикл быстрее?

7 задачек по информатике для тех, кто начинает изучать Python

Нужна ли математика для начинающего программиста?

Понравилась статья? Поставьте лайк, подпишитесь на канал! Вам не сложно, а мне очень приятно :)

Если Вам нужен репетитор по физике, математике или информатике/программированию, Вы можете написать мне или в мою группу Репетитор IT mentor в VK
Библиотека с книгами для физиков, математиков и программистов
Репетитор IT mentor в telegram