ЕГЭ · Информатика · Обработка последовательностей и файлов данных (задания 17, 25, 26, 27)
Задание 17: числовые последовательности и пары
Отработать типовые вопросы 17: сколько элементов, наибольшая сумма пары, условия на цифры.
🎯 ЕГЭ информатика: этот урок закрывает задание(я) 17.
- ⚠Читают файл не полностью или неверно разбирают строки в числа
- ⚠Забывают дополнительное условие (кратность, пара соседних, диапазон)
Задание 17: последовательности и пары
Стратегия решения
• Прочитать данные из файла в список.
• Если нужно — первым проходом посчитать вспомогательные величины (среднее, минимум).
• Вторым проходом собрать ответ (количество и максимум/сумму).
Пять типовых формулировок задания 17 и как их решать
Задание 17 всегда просит два числа: количество чего-то и максимум (или сумму). Меняется только условие отбора, и вариантов у него немного. Тип 1: условие на один элемент. «Количество элементов, кратных 3, и наибольший из них». Решается одним проходом с двумя накопителями. Тип 2: условие на пару соседних. «Количество пар, сумма которых делится на 13, и наибольшая из таких сумм». Здесь идут по индексам: for i in range(len(a) - 1), пара — это a[i] и a[i+1]. Пар на одну меньше, чем элементов. Тип 3: условие зависит от всей последовательности. «Элементы, превышающие среднее арифметическое» или «большие минимального». Такое условие невозможно проверить, пока не прочитаны все данные, поэтому нужны два прохода: первым считаем характеристику, вторым отбираем. Тип 4: условие на цифры числа. «Элементы, в записи которых есть цифра 7» или «сумма цифр которых кратна 5». Удобнее всего переводить число в строку: '7' in str(x). Тип 5: условие на диапазон. «Элементы, лежащие в промежутке от A до B». В Python двойное неравенство пишется естественно: if A <= x <= B. Общий порядок работы. 1. Прочитать все числа в список. 2. Если условие зависит от всей последовательности — сделать первый проход и посчитать нужную величину. 3. Сделать основной проход с двумя накопителями. 4. Напечатать оба ответа в том порядке, в каком их просят. Последний пункт важнее, чем кажется: за задание 17 дают один балл, и он снимается целиком, если перепутан порядок двух чисел.
| Кратно k | x % k == 0 |
|---|---|
| Последняя цифра d | x % 10 == d |
| Сумма цифр | sum(int(c) for c in str(abs(x))) |
| Содержит цифру d | str(d) in str(x) |
| Двузначное | 10 <= abs(x) <= 99 |
Пар соседних элементов на один меньше, чем самих элементов: цикл до len(a)−1, иначе a[i+1] вылезет за границу и программа упадёт с ошибкой индекса.
Разбор примера
Количество и максимум по условию
Найти количество элементов, кратных 3, и максимальный из таких элементов.
Показать решение по шагам
- 1.
cnt = 0 mx = None for x in a: if x % 3 == 0: cnt += 1 if mx is None or x > mx: mx = x print(cnt, mx) - 2. Накопители заводим до цикла: cnt считает подходящие элементы, mx хранит максимум среди них. Стартовое значение mx = None означает «ещё ничего не встретили».
- 3. Отступы здесь — часть смысла: проверка кратности стоит внутри цикла, а обновление mx — внутри этой проверки, поэтому максимум ищется только среди кратных трём.
- 4. После цикла cnt и mx уже готовы: печатаем их одной строкой.
Ответ: Пара (количество, максимум) за один проход
Разбор примера
Разбор: условие зависит от всей последовательности
В файле последовательность чисел. Найти количество элементов, которые больше среднего арифметического всей последовательности, и максимальный из них.
Показать решение по шагам
- 1. Почему одного прохода мало. Чтобы проверить «больше среднего», надо знать среднее, а оно становится известно только после того, как прочитаны все числа. Значит, проходов будет два.
- 2.
a = list(map(int, open('input.txt').read().split()))
sred = sum(a) / len(a) # первый проход — уже сделан функцией sum
cnt = 0 mx = None for x in a: if x > sred: cnt += 1 if mx is None or x > mx: mx = xprint(cnt, mx)
- 3. Первый проход здесь спрятан в функции sum(a): она сама проходит по списку. Считать среднее вручную циклом не нужно.
- 4. Деление обычное, а не целочисленное: среднее арифметическое почти никогда не целое, и округлять его нельзя — условие сравнивается с точным значением.
- 5. Второй проход отбирает элементы и обновляет оба накопителя внутри одной проверки.
- 6. Проверка на малом примере: для [1, 2, 3, 10] среднее равно 4, больше него только 10 — значит, ответ «1 10».
- 7. Осторожно с формулировкой: «не меньше среднего» означает >===, а «больше среднего» — ==>. Один знак меняет ответ.
Ответ: cnt и mx печатаются через пробел
Разбор примера
Наибольшая сумма пары соседних элементов
В последовательности a найти наибольшую сумму двух соседних элементов, у которых хотя бы один кратен 5.
Показать решение по шагам
- 1. best = None — накопитель лучшей суммы.
- 2. Идём по индексам: for i in range(len(a) - 1): пара — a[i] и a[i+1].
- 3. Условие пары: a[i] % 5 == 0 or a[i+1] % 5 == 0.
- 4. Если условие верно: s = a[i] + a[i+1]; if best is None or s > best: best = s.
- 5. После цикла best — ответ.
Ответ: best — наибольшая подходящая сумма пары
Вопрос на проверку
Как на Python проверить, что число x кратно 7?
Ответить и проверить себя — после бесплатной регистрации.
Вопрос на проверку
В последовательности 10 элементов. Сколько в ней пар соседних элементов?
Ответить и проверить себя — после бесплатной регистрации.
Вопрос на проверку
В каком случае задание 17 требует двух проходов по данным?
Ответить и проверить себя — после бесплатной регистрации.
Вопрос с развёрнутым ответом
Почему в задании 17 часто нужно сделать ДВА прохода по данным, а не один?
Ответить и проверить себя — после бесплатной регистрации.
Разбор примера
Полная программа линии 17 с трассировкой по парам
Дана последовательность 14, 7, 22, 9, 30, 3, 18, 25. Определите количество пар соседних элементов, у которых ровно один элемент кратен трём, и максимальную из сумм элементов таких пар.
Показать решение по шагам
- 1.
a = [int(x) for x in open('17.txt')]
kolichestvo = 0 maksimum = 0 for i in range(len(a) - 1):x, y = a[i], a[i + 1]
if (x % 3 == 0) != (y % 3 == 0): # ровно один кратен трём kolichestvo += 1 if x + y > maksimum: maksimum = x + yprint(kolichestvo, maksimum)
- 2. Шаг 0. Ключевая строка — условие. «Ровно один» это исключающее ИЛИ, и записывается оно как неравенство двух логических значений: скобки дают
True/False, и они различаются ровно тогда, когда кратен трём один элемент из двух. - 3. Элементов восемь, значит пар семь. Начальное состояние: количество 0, максимум 0.
- 4. Пара (14, 7). Ни 14, ни 7 не кратны трём — оба условия ложны, они равны, значит «ровно один» не выполнено. Мимо.
- 5. Пара (7, 22). Снова ни один не кратен трём. Мимо.
- 6. Пара (22, 9). 22 не кратно, 9 кратно — условия различаются ✔ количество 1, сумма 31 > 0 → максимум 31.
- 7. Пара (9, 30). Оба кратны трём — условия совпадают, «ровно один» не выполнено. Мимо. Вот здесь и проявляется разница с обычным «или»: оно приняло бы эту пару за подходящую.
- 8. Пара (30, 3). Оба кратны. Мимо.
- 9. Пара (3, 18). Оба кратны. Мимо.
- 10. Пара (18, 25). 18 кратно, 25 нет ✔ количество 2, сумма 43 > 31 → максимум 43.
- 11. Ответ: 2 43.
- 12. Шаг 1. Проверка прикидкой. Кратных трём в последовательности четыре: 9, 30, 3, 18 — и три из них стоят подряд (30, 3, 18), образуя пары «оба кратны». Поэтому подходящих пар оказалось всего две — на границах этой цепочки. Такое рассуждение занимает секунды и сразу показывает, не сбились ли вы в трассировке.
- 13. Шаг 2. Короче условие можно записать так:
(x % 3 == 0) + (y % 3 == 0) == 1. Логические значения в Python складываются как 0 и 1, и сумма равна единице ровно при «ровно одном». Оба варианта верны, выбирайте тот, который вам понятнее с первого взгляда.
Ответ: 2 43
Разбор примера
Та же программа, другое условие: модуль разности
В последовательности 14, 7, 22, 9, 30, 3, 18, 25 найти количество пар соседних элементов, модуль разности которых делится на 5, и максимальную из сумм таких пар.
Показать решение по шагам
- 1. Меняется единственная строка шаблона:
if abs(x - y) % 5 == 0:. Чтение файла, цикл по индексам, два накопителя и печать остаются прежними. - 2. Выпишем модули разностей по всем семи парам: |14 − 7| = 7, |7 − 22| = 15, |22 − 9| = 13, |9 − 30| = 21, |30 − 3| = 27, |3 − 18| = 15, |18 − 25| = 7.
- 3. Делятся на 5 ровно два значения — обе пятнадцатки. Это пары (7, 22) и (3, 18).
- 4. Считаем суммы: 7 + 22 = 29 и 3 + 18 = 21. Максимум 29.
- 5. Ответ: 2 29.
- 6. Шаг 1. Зачем модуль. Без него разность 7 − 22 равна −15, и в Python
-15 % 5даёт 0 — здесь бы обошлось. Но привычка брать модуль там, где в условии написано «модуль разности», избавляет от необходимости каждый раз вспоминать, как ведёт себя остаток от отрицательного числа. А в условиях вида «разность не превышает 5» отрицательный результат сломал бы сравнение сразу. - 7. Шаг 2. Проверка прикидкой: делимость модуля разности на 5 означает, что оба числа дают одинаковый остаток при делении на 5. Остатки нашей последовательности: 4, 2, 2, 4, 0, 3, 3, 0. Совпадающие соседние остатки стоят на позициях 2–3 (оба 2) и 6–7 (оба 3) — ровно две пары ✔ Такая проверка через остатки быстрее, чем считать семь разностей.
Ответ: 2 29
Разбор примера
Условие, зависящее от всей последовательности
В той же последовательности найти количество пар, оба элемента которых больше среднего арифметического всех элементов, и максимальную из сумм таких пар.
Показать решение по шагам
- 1.
a = [int(x) for x in open('17.txt')]
sredneye = sum(a) / len(a) # первый проход
kolichestvo = 0 maksimum = 0 for i in range(len(a) - 1): # второй проходx, y = a[i], a[i + 1]
if x > sredneye and y > sredneye: kolichestvo += 1 if x + y > maksimum: maksimum = x + y print(kolichestvo, maksimum) - 2. Шаг 1. Здесь нужны два прохода, и это единственная формулировка линии 17, где одного не хватает. Причина в слове «всех»: среднее зависит от элементов, до которых цикл ещё не дошёл, поэтому считать его по ходу отбора нельзя.
- 3. Шаг 2. Первый проход. Сумма: 14 + 7 + 22 + 9 + 30 + 3 + 18 + 25 = 128. Элементов восемь, среднее = 128 / 8 = 16.
- 4. Шаг 3. Отмечаем, какие элементы больше 16: это 22, 30, 18 и 25. Остальные — 14, 7, 9, 3 — меньше.
- 5. Шаг 4. Второй проход по семи парам. (14, 7) — оба меньше, мимо. (7, 22) — семёрка меньше, мимо: условие требует обоих. (22, 9) — девятка меньше, мимо. (9, 30) — мимо. (30, 3) — мимо. (3, 18) — мимо.
- 6. Шаг 5. (18, 25) — 18 > 16 ✔ и 25 > 16 ✔ Пара подходит: количество 1, сумма 43.
- 7. Шаг 6. Ответ: 1 43. Обратите внимание, насколько мало пар проходит: подходящие элементы стоят вразбивку, и соседними оказываются только два последних.
- 8. Шаг 7. Про деление. Здесь среднее вышло целым, но так бывает не всегда, и округлять его нельзя. Целочисленное деление
sum(a) // len(a)при среднем 15,7 дало бы 15, и элемент, равный 15, ошибочно прошёл бы отбор. Пишите обычное/и сравнивайте с дробным числом — Python это умеет. - 9. Шаг 8. Та же схема из двух проходов нужна везде, где в условии стоят слова «всех», «всей последовательности», «максимального элемента последовательности». Правило простое: величина, которую считают по всему файлу, вычисляется до начала отбора.
Ответ: 1 43
Три ошибки, которые ломают верную программу
Шаблон линии 17 короткий, и логика в нём редко бывает неверной. Балл теряют на трёх вещах, к логике отношения не имеющих.
Граница цикла. Пар на одну меньше, чем элементов, поэтому индекс идёт до len(a) - 1. Написать range(len(a)) — значит обратиться к a[i + 1] за концом списка и получить IndexError. Ошибка громкая, и потому не опасная. Опаснее обратная: range(len(a) - 2) теряет последнюю пару молча, и ответ выглядит правдоподобным.
Перекрывающиеся пары. Каждый элемент, кроме первого и последнего, входит в две пары: как правый сосед и как левый. Разбиение последовательности на непересекающиеся пары «через одну» уменьшает ответ примерно вдвое. В условии написано «два идущих подряд элемента», а не «последовательность разбита на пары».
Порядок чисел в ответе. Сначала количество, потом максимальная сумма. Это написано в каждом условии линии 17, и на этом теряют балл при полностью верной программе. Возьмите за правило печатать оба числа одной командой print(kolichestvo, maksimum) — тогда порядок фиксируется один раз и не путается при переписывании в бланк.
Четвёртая ошибка, менее частая, но обидная: максимум суммы против максимального элемента. Условие просит наибольшую из сумм подходящих пар. Сравнивать надо x + y, а не x и y по отдельности. И стартовое значение для этого максимума можно брать нулём: суммы в линии 17 положительны, а если подходящих пар не нашлось вовсе, ноль и будет правильным ответом.
Пятое, о чём стоит помнить: проверяйте программу на короткой последовательности из условия, для которой ответ можно посчитать глазами. В заданиях линии 17 такой пример почти всегда приведён, и сверка с ним занимает полминуты.
Шестая ошибка стоит отдельно, потому что её не видно вовсе: чтение файла не до конца. Если строка данных заканчивается пустой строкой, int('') уронит программу — это заметно. А вот если в файле есть завершающий перевод строки и вы читаете через read().split(), всё пройдёт гладко. Разница между двумя способами чтения проявляется именно на краях файла, и потому первая строка отладки в любой задаче с файлом — это print(len(a), a[:3], a[-3:]).
Когда пара — не соседние элементы
Формулировка «под парой подразумеваются два идущих подряд элемента» стоит в линии 17 почти всегда, но не всегда. Встречается и другая: «пара — это любые два элемента последовательности», и тогда решение меняется существенно.
Что меняется в переборе. Соседних пар n − 1, а произвольных — n(n−1)/2. Для двух тысяч чисел это 2 тысячи против двух миллионов: перебор всё ещё возможен, но уже заметно дороже. Для ста тысяч чисел (линия 27) он становится невозможным вовсе, и там такие формулировки решают группировкой, а не перебором.
Как выглядит перебор произвольных пар. Два вложенных цикла, причём внутренний начинается не с нуля, а со следующего за внешним индекса:
for i in range(len(a)):
for j in range(i + 1, len(a)):
x, y = a[i], a[j]
Старт внутреннего цикла с i + 1 решает сразу две задачи: не берёт элемент в пару с самим собой и не считает одну и ту же пару дважды в разном порядке.
Как обойтись без перебора. Если условие на пару сводится к свойству каждого элемента по отдельности — «оба чётные», «оба больше среднего», «оба четырёхзначные», — считать пары не нужно. Достаточно посчитать, сколько элементов обладают свойством, и взять C(m, 2) = m(m−1)/2. А максимальная сумма получится из двух наибольших подходящих элементов.
Если же условие связывает элементы между собой — «сумма делится на 9», «модуль разности кратен 13», — работают корзины остатков: числа раскладывают по остатку от деления, и пары ищут между корзинами. Оба приёма разобраны в уроке про эффективность.
Практический вывод: прочитайте, что в условии названо парой, прежде чем писать цикл. Одно слово «подряд» меняет и сложность, и ответ.
И ещё одна формулировка, которую стоит узнавать: «пара — два элемента, стоящие через один» (то есть a[i] и a[i+2]). Она встречается редко, но ломает шаблон так же, как и «любые два»: граница цикла становится len(a) - 2, а пар оказывается n − 2. Общее правило для всех вариантов одно: выпишите на черновике, какие индексы образуют пару, и уже из этого получите границу цикла. Пять секунд на черновике надёжнее, чем попытка вспомнить правильную формулу.
Задание №17 в формате экзамена
Ответить и проверить себя — после бесплатной регистрации.
Задание №17 в формате экзамена
Ответить и проверить себя — после бесплатной регистрации.