Муниципальный этап, 7–8 классы всероссийской олимпиады по информатике: 7 задач с официальным разбором, к 3 из них наше решение на C++.
К задаче 1Муниципальный этап ВсОШ по информатике 2023/24, 7–8 классы.
Задачи тура
- 1Абстрактный плакатгеометрия, конструктив
- 2Максимальный потокграфы, максимальный поток
- 3Телефонный справочникстроки, жадный алгоритм
- 4Большая командабинарный поиск, электронные таблицы
- 5Ферзьматематика
- 6Рамка для рисункаматематика, перебор
- 7Задачи на печать!жадный алгоритм, разбор случаев
Отмечайте решённые: 0 из 7
1. Абстрактный плакат
Для оформления фасада музея абстрактного искусства необходимо изготовить плакат, на котором изображено несколько красных линий. На рисунке изображён плакат и нарисована система координат.

Для рисования плаката у вас есть устройство, которое умеет рисовать границы прямоугольников, заданных координатами двух противоположных углов. Одна команда для устройства состоит из четырёх чисел. Первые два числа являются координатами и одного угла прямоугольника, следующие два числа являются координатами и противоположного угла прямоугольника. При этом и . Нарисованные прямоугольники могут иметь общие углы и общие стороны, как целиком, так и частично.
В одной строке записывается одна команда — четыре числа через пробел.
Например, для рисования такого плаката

достаточно двух команд устройства. Один из возможных вариантов решения для этого примера:
1 1 5 2
3 1 4 4
Запишите набор команд, необходимый для рисования данного плаката, содержащий минимальное число команд. Чем меньше команд будет в вашем алгоритме, тем больше баллов вы получите.
Для удобства решения задачи вы можете скачать файл для редактора электронных таблиц, содержащий данное изображение.
Скачать файл в формате Microsoft Excel.
Скачать файл в формате Libre Office Calc.
Официальный разборСначала попробуйте решить сами
Официальный разбор
Можно заметить, что картинка совпадает с собой при повороте на , поэтому количество прямоугольников в ответе будет делиться на 4. Для начала нарисуем выступающий единичный квадрат, сделаем этот прямоугольник, чтобы нарисовать всю верхнюю горизонтальную сторону (без выступающего сверху квадрата).

Нарисуем ещё три прямоугольника, полученные из данного поворотами.

Оставшиеся линии можно нарисовать при помощи четырёх прямоугольников. Всего достаточно 8 прямоугольников.
Пример такого ответа:
1 7 8 8
7 9 8 2
2 2 9 3
2 1 3 8
3 3 4 8
3 6 8 7
6 2 7 7
2 3 7 42. Максимальный поток
Дана сеть из нескольких труб, которые соединяются между собой в узлах, обозначенных буквами от «A» до «I». Для каждой трубы задана пропускная способность этой трубы (числа, написанные на трубах) — максимальный объём воды, который может пройти через эту трубу за единицу времени. Вода может течь по трубе в любом направлении.

Вам необходимо организовать передачу максимального объёма воды из узла «A» (исток) в узел «I» (сток).
Укажите, по каким трубам в каком направлении и в каком объёме необходимо организовать подачу воды. Ваша схема должна удовлетворять следующим условиям.
1. Объём воды, который протекает по трубе, не должен превышать пропускной способности этой трубы.
2. По каждой трубе вода течёт в одном направлении.
3. Для всех вершин, кроме истока «A» и стока «I», объём втекающей в узел воды должен быть равен объёму вытекающей из узла воды.
Чем больше будет пропускная способность вашей схемы (объём воды, передаваемый из «A» в «I» за единицу времени), тем больше баллов вы получите.
В ответе запишите несколько строк. Каждая строка должна содержать сначала две буквы, потом число. Две буквы должны быть концами одной трубы. Вода течёт по трубе из узла, обозначенного первой буквой, в узел, обозначенный второй буквой. Число обозначает объём воды, который протекает по этой трубе за единицу времени.
Например, запись
A B 5
обозначает, что по трубе из узла «A» в узел «B» будет протекать 5 единиц объёма воды в единицу времени.
Официальный разборСначала попробуйте решить сами
Официальный разбор
В терминах теории графов узлы будем называть вершинами, трубы — рёбрами, пропускную способность ребра — его весом. А такая задача известна, как задача нахождения максимального потока в графе.
Сумма весов рёбер исходящих из истока и входящих в сток равна 18, поэтому поток не может быть больше 18. Но посмотрим жёлтую линию («разрез»), отделяющий вершины и от вершин , , . Сумма весов рёбер, которые пересекает этот разрез, равна 16, поэтому величина потока не может быть больше 16.

Чтобы получить максимальный результат нужно «насытить» эти рёбра, то есть пустить по ним максимальный объём воды. Получим такую часть ответа.
B C 8
B E 4
D E 2
D G 2

Объём вытекающей из воды равен 12, поэтому необходимо сделать сумму весов входящих в рёбер тоже равным 12, для этого нужно будет подать из в объём 3 и насытить ребро . По ребру нужно будет подать 7, из которых 3 пойдёт в вершину и по 2 — в вершины и .
A B 9
A D 7
D B 3

Теперь посмотрим на второй жёлтый разрез, отделяющий вершины , , от вершин и .

Сумма весов рёбер, пересекающих разрез, равно 17, значит, нужно насытить все рёбра, кроме одного. Например, пустим через ребро объём 6.
C F 3
E F 2
E H 6
G H 5

Теперь направим воду из в и из в так, чтобы обеспечить нужный объём входящей воды в и :
C E 5
E G 3

Наконец, распределим воду по последним рёбрам. Поскольку в втекло 11, а вытечь может не более 9, то нужно направить 2 единицы воды из в .
H F 2
H I 9
F I 7

3. Телефонный справочник
Саша недавно начала регистрировать компанию по разработке чат-ботов и уже подала необходимые документы. Но добрые люди рассказали Саше, что в телефонном справочнике компании располагаются в лексикографическом (алфавитном) порядке их названий. Что такое телефонный справочник, Саша не знает, но решила учесть рекомендации и поменять название своей компании, чтобы оно было как можно раньше в телефонном справочнике. Поскольку Саша уже подала документы, она не может полностью поменять название компании, но может сказать, что допустила опечатку, и поменять любые две буквы в названии местами. Помогите Саше выбрать новое название компании.
Вам предлагается 4 варианта названия:
1. cfwvfu
2. tbzttbetcb
3. aefhfifjfkflzhz
4. abcdfjhklmnqrtuvwzyx
Для каждого из этих названий предложите другое название, которое можно получить из этого перестановкой каких-то двух не обязательно соседних букв и которое при этом является минимально возможным в лексикографическом порядке.
Напомним, что из двух слов в лексикографическом порядке одно будет меньше другого, если у этих слов есть какая-то общая совпадающая начальная часть (возможно, пустая), а следующий символ одного слова идёт в алфавите раньше, чем следующий символ другого слова. Если вы забыли английский алфавит, запустите приложение для работы с электронными таблицами и посмотрите на обозначения столбцов таблицы.
Запишите ответы для каждого из четырёх названий, каждый ответ — в отдельной строке. В каждой строке должны быть только английские буквы, номер задания указывать не нужно. В вашем ответе должно быть ровно 4 строки. Если вы не можете дать ответ на какое-то задание, напишите любую строку из английских букв, например, “a”.
Официальный разборСначала попробуйте решить сами
Официальный разбор
Давайте рассматривать символы по одному, начиная с первого. Чтобы получить как можно меньшую строку, мы должны найти самый первый символ, который можно заменить на меньший, то есть правее которого есть меньший.
Рассмотрим первое задание “cfwvfu”. Для символов “c” и “f” правее нет меньшего символа, а для символа “w” — есть, это предпоследний символ “f”. Получим ответ “cffvwu”.
Рассмотрим второе задание “tbzttbetcb”. Здесь самый первый символ “t” можно заменить на меньший. Но чтобы строка была лексикографически наименьшей, мы должны выбрать справа наименьший из возможных символов для замены, это символ “b”. Но и символов “b” в строке несколько, поскольку выбранный символ “b” мы заменим на больший, то нужно использовать для перестановки последний символ “b”. Получим ответ “bbzttbetct”.
В третьем задании дана строка “aefhfifjfkflzhz”. Здесь самый первый символ, правее которого есть меньший — это “h”. Поменяем его с последним вхождением символа “f”, получим ответ “aefffifjfkhlzhz”.
В четвёртом задании “abcdfjhklmnqrtuvwzyx” можно заменить символ “j” на меньший символ ”h”, стоящий правее него. Получим “abcdfhjklmnqrtuvwzyx”.
4. Большая команда
Для участия в городском школьном турнире по кёрлингу необходимо пригласить команд. Команда должна состоять из учащихся одной школы, при этом от одной школы могут принять участие несколько команд. Организаторы решили для популяризации игры внести изменения в правила игры — все команды могут состоять не обязательно из четырёх участников, но размеры команд должны быть равны. Это позволит привлечь к игре больше школьников.
Теперь перед организаторами стоит сложная задача — необходимо определить такое максимальное значение , чтобы из всех школ города можно было собрать команд, в каждой из которых было бы участников из одной школы. Например, если в какой-то школе имеется 500 учащихся и размер команды равен 20, то из этой школы смогут принять участие 25 команд, а если взять равным 21, то возможно собрать только 23 команды из этой школы.
Дано количество обучающихся в каждой школе города и количество команд , которое необходимо собрать. Вы должны определить максимально возможный размер команды для этих данных.
Данные для этой задачи находятся в документе электронной таблицы.
Скачать таблицу в формате Microsoft Excel.
Скачать таблицу в формате Libre Office Calc.
В этой таблице четыре листа, на каждом листе находится отдельный набор данных, для которого вам необходимо выполнить задание. На каждом листе в столбце A записаны количества учащихся во всех школах города, а в ячейке C2 записано значение для этого набора — количество команд, которое необходимо пригласить для участия в турнире.
Запишите в ответе четыре целых числа, являющиеся ответами на задание для каждого листа таблицы, в порядке следования листов в таблице. Каждое число пишите в отдельной строке. Вы должны записать ровно 4 числа, если вы не можете дать ответ на какое-то задание, напишите любое число.
Официальный разборСначала попробуйте решить сами
Официальный разбор
В первом задании школ мало и ответ можно найти просто изучив входные данные, он равен 14.
Во втором задании школ уже довольно много, поэтому понадобится провести некоторые вычисления. Например, запишем в ячейку D1 количество участников в команде. В ячейку D2 запишем формулу для вычисления количества команд из школы в строке 2: =INT($A2/D$1) — нужно поделить количество учащихся в школе на размер команды и взять целую часть. Теперь скопируем эту формулу на весь столбец D. Посчитаем сумму чисел в столбце D, то есть количество получившихся команд. Для этого можно использовать формулу типа =SUM(C2:C1001). Будем менять значение в ячейке D1, пока эта сумма не станет больше или равна необходимого количества команд. Это произойдёт при размере команды, равном 22.
Аналогично можно решить и оставшиеся задания, только сложность будет с перебором значения размера команды. В задании 3 можно заполнить ячейки в строке 1 возможными значениями команды: 1, 2, 3, и т.д. А в столбце ниже него посчитать количество команд, которое получится при данном размере. Максимальный размер команды, при котором наберётся нужное количество команд, будет равен 379.
В четвёртом задании числа столь большие, что такой подход потребует слишком много вычислений. Можно подобрать нужный размер, например, сначала увеличивая размер команды с шагом 1000. Затем определив диапазон для ответа из 1000 чисел, заполнить строку с размером команды с шагом 1. Или можно интерактивно менять значение в ячейке, увеличивая или уменьшая его, сокращая диапазон поиска. Например, сначала определить, что ответ находится от 200 000 до 300 000. Потом подобрать вторую цифру ответа, ответ будет находиться от 210 000 до 220 000. Затем подобрать третью цифру и т.д. Ответ на четвертое задание — 218 976.
5. Ферзь
Пётр любит шахматы и математику. Он знает, что самая мощная фигура в шахматах — это ферзь, потому что он ходит и как ладья, на все клетки на одной с ним вертикали или горизонтали, и как слон, на все клетки по диагоналям. Ферзя можно поставить на доску так, чтобы он контролировал (то есть мог переместиться в эти клетки за один ход) целых 27 клеток доски!
Петра заинтересовало, какое максимальное количество клеток может контролировать ферзь на прямоугольных досках самых разных размеров. Помогите ему в решении этой задачи.
Формат входных данных
Первая строка входных данных содержит целое число () — размер доски по вертикали.
Вторая строка входных данных содержит целое число () — размер доски по горизонтали.
Формат выходных данных
Программа должна вывести одно целое число — максимальное количество клеток, которое может контролировать ферзь на доске .
Обратите внимание на то, что ответ в этой задаче может превышать возможное значение 32-битной целочисленной переменной, поэтому необходимо использовать 64-битные целочисленные типы данных (тип long long в языке C++, тип int64 в Pascal, тип long в Java и C#).
Система оценки
Решения, правильно работающие, когда и не превосходят , будут оцениваться в 40 баллов.
Решения, правильно работающие, когда и не превосходят , будут оцениваться в 80 баллов.
Замечание
Второй пример из условия приведён на рисунке. Крестиками обозначены клетки, которые контролирует ферзь.

| стандартный ввод | стандартный вывод |
|---|---|
8 8 | 27 |
| стандартный ввод | стандартный вывод |
|---|---|
3 4 | 9 |
Официальный разборСначала попробуйте решить сами
Наше решение на C++Полный код на C++17
Официальный разбор
Чтобы набрать 40 баллов достаточно написать решение, перебирающее все клетки, на которые можно поставить ферзя. Затем нужно посчитать количество клеток, которые бьёт этот ферзь. Для этого также переберём все оставшиеся клетки доски, и проверим, находятся ли они в одной горизонтали, вертикали или диагонали с выбранной клеткой. Запомним наибольшее количество клеток, которое может бить ферзь. Сложность такого решения будет . В примере такого решения строки и столбцы доски нумеруются для удобства с нуля.
n = int(input())
m = int(input())
ans = 0
for x in range(n):
for y in range(m):
count = 0
for xx in range(n):
for yy in range(m):
if x == xx or y == yy or x - xx == y - yy or x - xx == yy - y:
count += 1
ans = max(ans, count - 1)
print(ans)Чтобы набрать 80 баллов, нужно уменьшить сложность решения до . Для этого можно находить количество клеток, которые бьёт ферзь, без цикла, то есть за . Или, наоборот, заметить, что ферзя нужно поставить в центр доски, и найти циклами количество клеток, которые он бьёт. Пример второго решения, где ферзь ставится в клетку с координатами .
n = int(input())
m = int(input())
x = n // 2
y = m // 2
count = 0
for xx in range(n):
for yy in range(m):
if x == xx or y == yy or x - xx == y - yy or x - xx == yy - y:
count += 1
print(count - 1)Полное решение имеет сложность . Здесь нужно заметить, что ферзь контролирует наибольшее количество клеток, находясь в центре доски, и посчитать их количество, без использования циклов.
Пусть , то есть доска “вытянута” по горизонтали, иначе поменяем значения и . Тогда в одной горизонтали с ферзём находятся клетка, а в одной вертикали — клетка. Диагонали, проходящие через ферзя, также могут содержать не более клеток (поэтому в каждой из них не более клетки, за вычетом клетки, в которой стоит ферзь), поэтому ответ будет равен . Но есть одно исключение: на квадратной доске, сторона которой имеет чётную длину, одна из диагоналей будет короче на одну клетку. Это, например, случай доски (первый пример из условия), для которой ответ равен 27, а не 28. Почему так происходит, можно видеть на рисунке.

В этом случае просто вычтем 1 из ответа. Пример такого решения.
n = int(input())
m = int(input())
if n > m:
n, m = m, n
ans = 3 * n + m - 4
if n % 2 == 0 and m == n:
ans -= 1
print(ans)Наше решение на C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n, m;
cin >> n >> m;
if (n > m) swap(n, m);
long long answer = 3 * n + m - 4;
if (n % 2 == 0 && n == m) answer -= 1;
cout << answer << "\n";
return 0;
}6. Рамка для рисунка
У Алексея есть набор, который состоит из палочек длины 1 и палочек длины 2. Палочки можно соединять между собой, либо выстраивая их в линию, либо под прямым углом.
Алексей хочет собрать из имеющихся палочек рамку прямоугольной формы, чтобы потом вставить в эту рамку лист бумаги и нарисовать красивый пейзаж для мамы на Новый год.
При этом Алексей считает, что чем больше будет площадь прямоугольника, тем значимей будет его подарок. Поэтому ему важно определить максимальную площадь прямоугольника, границу которого можно собрать из имеющихся палочек.
Формат входных данных
Первая строка входных данных содержит целое число — количество палочек длины 1, .
Вторая строка входных данных содержит целое число — количество палочек длины 2, .
Формат выходных данных
В единственной строке выведите единственное целое число — максимальную площадь прямоугольника, который можно сложить из имеющихся палочек. Если из имеющихся палочек невозможно сложить никакой прямоугольник, то выведите число 0.
Обратите внимание на то, что ответ в этой задаче может превышать возможное значение 32-битной целочисленной переменной, поэтому необходимо использовать 64-битные целочисленные типы данных (тип long long в языке C++, тип int64 в Pascal, тип long в Java и C#).
Система оценки
Решения, правильно работающие, когда и не превосходят , будут оцениваться в 20 баллов.
Решения, правильно работающие, когда и не превосходят , будут оцениваться в 40 баллов.
Решения, правильно работающие, когда и не превосходят , будут оцениваться в 60 баллов.
Замечание
В первом примере есть 5 палочек длины 1. Из них можно сложить квадрат со стороной 1, его площадь равна 1, при этом одна палочка останется.
Во втором примере есть 4 палочки длины 1 и 3 палочки длины 2. Из них можно сложить прямоугольник размера .
В третьем примере есть 3 палочки длины 1, из них невозможно сложить прямоугольник.
| стандартный ввод | стандартный вывод |
|---|---|
5 0 | 1 |
| стандартный ввод | стандартный вывод |
|---|---|
4 3 | 6 |
| стандартный ввод | стандартный вывод |
|---|---|
3 0 | 0 |
Официальный разборСначала попробуйте решить сами
Наше решение на C++Полный код на C++17
Официальный разбор
Начнём с переборных решений, набирающих частичные баллы. Пусть и — количество палочек длины 1 и 2 соответственно.
40 баллов можно набрать, если перебирать две стороны прямоугольника и . Проверим, можно ли сложить из имеющихся палочек прямоугольник . Должны выполняться два условия: общая длина всех палочек должна быть не меньше периметра прямоугольника, равного , и каждая сторона нечётной длины должна содержать хотя бы одну палочку длины 1, поэтому значение должно быть не меньше количества нечётных чисел среди сторон . Пример такого решения.
n1 = int(input())
n2 = int(input())
max_side = (n1 + 2 * n2) // 2
ans = 0
for a in range(1, max_side + 1):
for b in range(1, max_side + 1):
if n1 + 2 * n2 >= 2 * a + 2 * b and n1 >= 2 * (a % 2 + b % 2):
ans = max(ans, a * b)
print(ans)Чтобы набрать 60 баллов нужно перебирать только одну сторону, а не две. Пусть это сторона . Максимальное значение одной стороны, как и в предыдущем решении, равно (целочисленное частное от деления суммы длин всех палочек на 2). Тогда у нас будет две стороны длины . Проверим условие, что не меньше, чем , то есть если — нечётное, то найдётся хотя бы две палочки длины 1.
Теперь определим наибольшее подходящее значение для данного значения . Для этого посчитаем длину оставшихся палочек и поделим её на 2. При этом могло оказаться, что , то есть значение оказалось меньше, чем число нечётных чисел среди значений , то нам не хватит палочек длины 1 для того, чтобы собрать нечётные отрезки длины . Но ранее мы проверили, что нам хватает палочек длины 1 для того, чтобы собрать только отрезки и , поэтому это возможно только в случае нечётного . В этом случае уменьшим значение на 1. Так мы определяем наибольшее значение второй стороны для ранее выбранной стороны . Запомним наибольшее из значений площадей прямоугольников .
n1 = int(input())
n2 = int(input())
max_side = (n1 + 2 * n2) // 2
ans = 0
for a in range(1, max_side + 1):
if n1 < 2 * (a % 2):
continue
b = (n1 + 2 * n2 - 2 * a) // 2
if n1 < 2 * (a % 2 + b % 2):
b -= 1
ans = max(ans, a * b)
print(ans)Чтобы написать полное решение, нужно избавится и от перебора всех возможных значений одной стороны. Нужно заметить, что среди всех прямоугольников с одинаковым периметром максимальная площадь будет у квадрата или у прямоугольника, стороны которого различаются на 1. Действительно, пусть прямоугольник имеет стороны , при этом . Рассмотрим прямоугольник с таким же периметром. Его площадь будет равна , то есть больше площади .
Поэтому для максимизации периметра в качестве значения одной из сторон нужно выбрать от максимально возможного периметра. Для этого в качестве значения минимальной стороны возьмём значение , а значение подберём наибольшее подходящее значение, как в предыдущем решении. Но если значение оказалось нечётным, то для формирования сторон длины понадобится минимум 2 палочки длины 1, и, возможно, нам не хватит палочек длины 1 для достижения максимально возможного значения . Поэтому необходимо рассмотреть как чётное, так и нечётное значение , то есть нужно взять не только , но и значение на 1 меньше — , так как одно из них будет чётным. Для каждого из этих значений выберем подходящее и найдём наибольшее значение .
Пример такого решения.
n1 = int(input())
n2 = int(input())
ans = 0
side = (n1 + 2 * n2) // 4
for a in range(side - 1, side + 1):
if n1 < 2 * (a % 2):
continue
b = (n1 + 2 * n2 - 2 * a) // 2
if n1 < 2 * (a % 2 + b % 2):
b -= 1
ans = max(ans, a * b)
print(ans)Есть и другие способы решения задачи. Например, можно попробовать конструктивно построить решение так, чтобы две стороны прямоугольника оказались максимально большими и при этом близки друг к другу. Для этого сначала разложим палочки длины 2 поровну на все стороны. У нас останется 0, 1, 2 или 3 палочки длины 2. Если осталось хотя бы две палочки длины 2, то увеличим на 2 длины двух сторон . Если после этого осталась хотя бы одна палочка длины 2 и ещё одна палочка длины 2 или две палочки длины 1, то также можно сторону увеличить на 2. Иначе попробуем используя палочки длины 1 выровнять длины сторон. После выравнивания длин сторон все оставшиеся палочки длины 1 разложим поровну по всем сторонам. После этого останется не более трёх палочек длины 1, если их две или три — то можно длины двух сторон увеличить на 1.
Сложность реализации такого решения в том, что нужно аккуратно рассмотреть все случаи, не пропустив ни одного.
n1 = int(input())
n2 = int(input())
a = 2 * (n2 // 4)
b = 2 * (n2 // 4)
n2 %= 4
if n2 >= 2:
n2 -= 2
a += 2
if n2 == 1 and n1 >= 2:
b += 2
n2 = 0
n1 -= 2
while a < b and n1 >= 2:
a += 1
n1 -= 2
while a > b and n1 >= 2:
b += 1
n1 -= 2
a += n1 // 4
b += n1 // 4
n1 %= 4
if n1 >= 2:
a += 1
print(a * b)Наше решение на C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long ones, twos;
cin >> ones >> twos;
long long total = ones + 2 * twos;
long long side = total / 4;
long long best = 0;
for (long long a = side - 1; a <= side; a++) {
if (a < 1) continue;
if (ones < 2 * (a % 2)) continue;
long long b = (total - 2 * a) / 2;
if (ones < 2 * (a % 2 + b % 2)) b -= 1;
if (b < 1) continue;
best = max(best, a * b);
}
cout << best << "\n";
return 0;
}7. Задачи на печать!
Олимпиады бывают не только личные, но и командные. В командной олимпиаде по программированию обычно принимают участие команды из трёх человек, которым предоставляется один компьютер и один комплект условий задач, причём задач обычно существенно больше, чем в личных олимпиадах.
Условие каждой из задач помещается на одной, двух или трёх страницах. При этом условие может быть напечатано на двух сторонах одного листа, но для удобства команд на одном листе может располагаться условие только одной из задач. Для экономии бумаги, если условие задачи занимает две страницы, оно должно быть напечатано на двух сторонах одного листа, а если из трёх страниц — на двух сторонах одного листа и на одной стороне другого листа, вторая сторона которого останется чистой. При этом можно напечатать первую страницу такой задачи отдельно на чистом листе, а оставшиеся две страницы — на одном листе или, наоборот, первые две страницы распечатать на одном листе, а третью — на чистом листе. Задачи и все их страницы печатаются последовательно.
Условия всех задач распечатываются на принтере в виде нескольких последовательных заданий. Для каждого задания необходимо задать диапазон печати: номера первой и последней страниц, которые будут напечатаны в этом задании (будут напечатаны все страницы в этом диапазоне), а также тип печати — односторонняя или двусторонняя.
Вам необходимо минимизировать количество заданий для печати условий.
Формат входных данных
Первая строка входных данных содержит целое число () — количество задач в олимпиаде.
Следующие строк содержат по одному целому числу () — количество страниц в -й задаче.
Формат выходных данных
Выведите единственное число — минимальное количество последовательных диапазонов, каждый из которых можно напечатать одной командой односторонней или двусторонней печати так, что условия всех задач будут напечатаны в удобном для командной олимпиады виде.
Система оценки
Решения, верно работающие, когда все значения отличны от 1, будут оцениваться не менее чем в 30 баллов.
Решения, верно работающие, когда все значения отличны от 2, будут оцениваться не менее чем в 30 баллов.
Решения, верно работающие, когда все значения отличны от 3, будут оцениваться не менее чем в 30 баллов.
Решения, верно работающие, когда , будут оцениваться не менее чем в 50 баллов.
Решения, верно работающие, когда , будут оцениваться не менее чем в 80 баллов.
Замечание
В первом примере на олимпиаду предложены 4 задачи, условия которых состоят из 1, 3, 2 и 1 страниц соответственно. Всего необходимо распечатать 7 страниц. Их можно распечатать за два задания: страницы 1–2 — односторонней печатью (это единственная страница первой задачи и первая из трёх страниц второй задачи), оставшиеся страницы 3–7 — двусторонней.
Во втором примере на олимпиаду предложены 2 задачи, условия которых состоят из 3 страниц каждая. Всего необходимо распечатать 6 страниц. Их можно распечатать за два задания: страницы 1–1 — односторонней печатью (это первая из трёх страниц первой задачи), оставшиеся страницы 2–6 — двусторонней. При этом в первой задаче первая страница будет напечатана на одной стороне, потому что она напечатана односторонней печатью, а во второй задаче последняя страница будет напечатана на одной стороне, потому что в этом задании нечётное число страниц печатается на двух сторонах, поэтому вторая сторона этого листа будет пустой.
| стандартный ввод | стандартный вывод |
|---|---|
4 1 3 2 1 | 2 |
| стандартный ввод | стандартный вывод |
|---|---|
2 3 3 | 2 |
Официальный разборСначала попробуйте решить сами
Наше решение на C++Полный код на C++17
Официальный разбор
Будем рассматривать задачи последовательно, определяя, в каком режиме должна быть напечатана очередная задача. Например, если в задаче 2 страницы, то её условие должно быть напечатана только в двустороннем режиме. А если в задаче 1 страница, то всё зависит от того, в каком режиме была напечатана предыдущая страница. Если это был односторонний режим, то мы расширим предыдущий диапазон печати на новую задачу, а если двусторонний — то эту одну страницу можно напечатать в двустороннем режиме, однако, следующая страница обязательно должна стать началом нового диапазона печати, который может быть как односторонним, так и двусторонним.
Заведём переменную mode, в которой будет храниться текущий режим печати — 1 для односторонней печати и 2 для двусторонней. Значение 0 означает, что очередная страница должна стать началом нового диапазона печати, который может быть любым. В переменной ans хранится общее число диапазонов печати. В переменной p хранится количество страниц в текущей задаче.
Далее нужно аккуратно разобрать все случаи. Если то мы обязательно переходим в режим 2, при этом если ранее режим был другим, то к ответу прибавляем 1.
Если , то в режиме 1 не нужно делать ничего, в режиме 2 эта страница печатается в двустороннем режиме, но нужно перейти в режим 0 для начала нового диапазона со следующей страницы (потому что на обороте этой страницы ничего нельзя печатать), а в режиме 0 нужно перейти в режим 1, начав новый диапазон, то есть добавив к ответу 1.
Наконец, разберём случай . Если до этого был режим 1, то мы печатаем одну страницу односторонней печатью, а ещё две страницы — двусторонней, поэтому нужно перейти в режим 2. Если мы были в режиме 2, то все три страницы можно напечатать в двустороннем режиме, потом нужно перейти в режим 0, потому что придётся начать новый диапазон. Аналогично поступим, когда режим был равен 0 — начнём новый двусторонний режим, напечатаем три страницы, а затем придётся начать новый диапазон, то есть в этом случае нужно просто увеличить значение ans на 1, сохранив значение mode равным 0.
Пример такого решения.
ans = 0
mode = 0
n = int(input())
for i in range(n):
p = int(input())
if p == 1:
if mode == 2:
mode = 0
elif mode == 0:
mode = 1
ans += 1
if p == 2:
if mode != 2:
ans += 1
mode = 2
if p == 3:
if mode == 1:
mode = 2
ans += 1
elif mode == 2:
mode = 0
else:
ans += 1
print(ans)Частичные решения можно получить используя полный перебор вариантов.
Задачу можно решить и динамическим программированием, в котором целевой функцией будет количество диапазонов, необходимое для печати первых задач. При этом придется ввести и второй параметр, аналогичный по смыслу переменной mode.
Наше решение на C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
long long ranges = 0;
int mode = 0;
for (int i = 0; i < n; i++) {
int pages;
cin >> pages;
if (pages == 1) {
if (mode == 2) {
mode = 0;
} else if (mode == 0) {
mode = 1;
ranges++;
}
} else if (pages == 2) {
if (mode != 2) {
ranges++;
mode = 2;
}
} else {
if (mode == 1) {
mode = 2;
ranges++;
} else if (mode == 2) {
mode = 0;
} else {
ranges++;
}
}
}
cout << ranges << "\n";
return 0;
}Сначала решите сами
Возьмите столько времени, сколько было на олимпиаде, и только потом открывайте разбор.
Другие туры
2026/27
- Школьный этап, 9–11 классы5 задач
- Школьный этап, 7–8 классы6 задач
- Школьный этап, 5–6 классы5 задач
2025/26
- Школьный этап, 9–11 классы5 задач
- Школьный этап, 7–8 классы6 задач
- Школьный этап, 5–6 классы5 задач
- Муниципальный этап, 9–11 классы5 задач
- Муниципальный этап, 7–8 классы6 задач
2024/25
- Школьный этап, 9–11 классы5 задач
- Школьный этап, 7–8 классы7 задач
- Школьный этап, 5–6 классы5 задач
- Муниципальный этап, 9–11 классы5 задач
- Муниципальный этап, 7–8 классы7 задач
2023/24
- Школьный этап, 9–11 классы5 задач
- Школьный этап, 7–8 классы7 задач
- Школьный этап, 5–6 классы5 задач
- Муниципальный этап, 9–11 классы5 задач
- Муниципальный этап, 7–8 классы7 задач