Подтема 5 из 5
Решение от результата
Как решить задачу темы без перебора N — идя от результата.
От результата к N
Вместо перебора N можно перебирать результаты: брать R от границы вверх, записывать в двоичной системе и проверять, мог ли алгоритм его выдать. Так решают задачу темы без программы — нужен только перевод чисел.
Алгоритм дописывает 10 к чётному N и 01 к нечётному. Значит, у подходящего R запись оканчивается на 10 или 01, а оставшаяся слева часть — запись N нужной чётности.
| R | Двоичная запись | Можно получить? |
|---|---|---|
| 151 | 100101 | 11 | нет: хвост 11 |
| 152 | 100110 | 00 | нет: хвост 00 |
| 153 | 100110 | 01 | нет: 100110 = 38 — чётное, а 01 дописывают к нечётным |
| 154 | 100110 | 10 | да: 38 чётное, дописано 10 |
Наименьший результат больше 150 — 154 при N = 38. Здесь справа всегда дописываются две цифры, поэтому больший N даёт больший R, и наименьшему R соответствует наименьшее N: ответ 38, как и в подтеме 4.
Тонкости:по ветвям формулами
Тот же ответ дают формулы ветвей.
Переводим действия в формулы: R = 4N + 2 для чётного N, R = 4N + 1 для нечётного.
Рассмотрим чётные N: 4N + 2 > 150, 4N > 148, N > 37. Минимальное чётное число, большее 37, — это 38. Проверка: R = 4 · 38 + 2 = 154.
Теперь нечётные N: 4N + 1 > 150, 4N > 149, N > 37,25. Первое целое число после 37,25 — это 38. Но оно чётное и к этой ветви не относится. Первое подходящее нечётное число — 39. Проверка: R = 4 · 39 + 1 = 157.
Сравниваем найденные входы: min(38, 39) = 38. Ответ: 38.
Так же нужно поступать с ветвями вида «N кратно 3», «остаток от деления N на 5 равен 2», «в записи чётное количество единиц», «сумма цифр делится на 3». Полученное из неравенства число обязательно проверяется на принадлежность рассматриваемой ветви.
Проверка хвоста
Иногда удобнее идти от результата обратно к исходному числу. Если алгоритм сохраняет запись N и дописывает справа две цифры, то запись R без двух последних цифр — это запись N, а две последние цифры — дописанный блок.
Возьмём алгоритм с двумя последовательными проверками суммы цифр и проверим, может ли он выдать R = 100. 100 = 1100100₂. Разделяем запись: 11001 | 00. Предполагаемый вход 11001₂ = 25. У числа 25 три единицы. Значит, по алгоритму нужно дописать 10, а не 00. Следовательно, 100 получить нельзя.
Проверим 102 = 1100110₂. Разделяем: 11001 | 10. Вход снова равен 25, хвост правильный. Значит, 102 получить можно.
Удаление хвоста находит предполагаемый вход. Затем всё равно нужно проверить, что алгоритм действительно создаёт именно такой хвост. Одного подходящего окончания результата недостаточно: оно должно согласовываться с исходной частью.
Итого
- Обратный ходперебираем R от границы и проверяем, мог ли он получиться
- Хвост записидолжен совпасть с тем, что алгоритм дописывает
- Остаток слеваэто N; его свойство (чётность, сумма цифр) проверяют
- R растёт с Nтогда наименьшему R соответствует наименьшее N
Проверьте себя
Ответь сначала сам, потом открой ответ.
ОтветСкрыть ответ
100111|01, хвост 01, а 100111 = 39 — нечётное. N = 39.ОтветСкрыть ответ
100111|00, хвоста 00 алгоритм не дописывает.ОтветСкрыть ответ
11001|00, предполагаемый вход 25 имеет три единицы и требует хвост 10.ОтветСкрыть ответ
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Найти N по результату
К двоичной записи числа N дописали справа единицу и получили 47. Найди N.
Введите число.
Подсказка
Дописать единицу справа — это 2N + 1.
Решение
Дописанная справа единица даёт R = 2N + 1. Из 47 = 2 · 23 + 1 получаем N = 23.
Решение программой
for n in range(1, 47): if int(bin(n)[2:] + '1', 2) == 47: print(n)Ответ: 23
Вход по результату 189
На вход алгоритма подаётся натуральное число N. Строится его двоичная запись; если N чётное, справа дописывается 10, если нечётное — 01. Полученная запись — двоичная запись числа R. Получилось R = 189. Найди N.
Введите число.
Подсказка
Раздели запись 189 на хвост из двух цифр и оставшуюся часть.
Решение
189 = 101111|01: хвост 01, слева 101111 = 47 — нечётное, а нечётным как раз дописывают 01. Значит, N = 47.
for n in range(1, 190): s = bin(n)[2:] if n % 2 == 0: s = s + '10' else: s = s + '01' if int(s, 2) == 189: print(n)Ответ: 47
Наименьший результат больше 200
На вход алгоритма подаётся натуральное число N. Строится его двоичная запись; если N чётное, справа дописывается 10, если нечётное — 01. Полученная запись — двоичная запись числа R. Найди наименьшее R, большее 200.
Введите число.
Подсказка
Проверяй числа 201, 202, … : хвост записи должен совпасть с дописанным блоком.
Решение
201 = 110010|01: слева 50 — чётное, а 01 дописывают к нечётным, не подходит. 202 = 110010|10: 50 чётное, дописано 10 — подходит.
best = 10 ** 9for n in range(1, 201): s = bin(n)[2:] if n % 2 == 0: s = s + '10' else: s = s + '01' r = int(s, 2) if r > 200: best = min(best, r)print(best)Ответ: 202