search icon search icon ВЕРСИЯ ДЛЯ СЛАБОВИДЯЩИХ

Предметный тур. Информатика. 3 этап

Информатика. 8–11 классы
Задача 1.1.(15 баллов)
Черно-белая таблица

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 1 с.

Ограничение по памяти: 256 Мбайт.

Условие

Робот двигается по таблице \(15 \times 15\).

Рис. 1.1.

Помогите роботу ответить на несколько запросов: по заданным координатам клетки нужно определить ее цвет.

Формат входных данных

В первой строке дано одно число \(t\) (\(1 \leqslant t \leqslant 225\)) — количество тестовых запросов.

В следующих \(t\) строках дано два целых числа \(r\) и \(c\) (\(1 \leqslant r, c \leqslant 15\)) — номер строки и столбца. Строки и столбцы нумеруются с левого верхнего угла с единицы.

Формат выходных данных

Выведите \(t\) строк — ответ на каждый запрос. Если клетка черная, выведите black, иначе — white.

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
2
3 5
4 5
black
white

Решение

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

В данной сетке квадрат окрашен в черный цвет, если «расстояние» от центрального квадрата до него нечетное, и в белый, если четное. В частности, квадрат на \(r\)-й строке и \(c\)-м столбце черный тогда и только тогда, когда расстояние Чебышева (шахматное расстояние) от центрального квадрата, \(\max(|r - 8|, |c - 8|)\), нечетное (здесь \(|x|\) обозначает абсолютное значение \(x\)).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
t = int(input())
for _ in range(t):
    n, m = map(int, input().split())
    x = min(n, 15 - n + 1)
    x = min(x, min(m, 15 - m + 1))
    print("black" if x % 2 == 1 else "white")

Задача 1.2.(18 баллов)
Робот-манипулятор

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 1 с.

Ограничение по памяти: 256 Мбайт.

Условие

Робот находится на прямой в ячейке 1.

Робот последовательно выполняет команды, которые написаны на ячейках. В ячейке под номером \(i\) находится команда переместиться в ячейку под номером \(a_i\). Возможно, что \(a_i = i\).

Сколько команд выполнит робот, чтобы добраться в ячейку под номером \(n\)?

Формат входных данных

В первой строке задано число \(n\) (\(2 \leqslant n \leqslant 10^5\)) — количество ячеек.

Во второй строке задано \(n\) чисел \(a_i\) (\(1 \leqslant a_i \leqslant n\)) — номер ячейки, в которую переместится робот, если окажется на \(i\)-й ячейке.

Формат выходных данных

Выведите единственное число — сколько команд выполнит робот, прежде чем окажется в \(n\)-й ячейке. Если робот не сможет оказаться в ячейке под номером \(n\), то выведите \(-1\).

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
3
3 1 2
1
2
4
3 4 1 2
-1
3
5
3 5 4 2 4
4

Решение

  1. Инициализация:

    • Текущая позиция: \(pos = 1\).
    • Счетчик команд: \(count = 0\).
    • Множество посещенных ячеек: \(visited = \varnothing\).
  2. Основной цикл:

    • Пока \(pos \neq n\) и \(pos \notin visited\):

      • Добавляем \(pos\) в \(visited\).
      • Перемещаемся: \(pos \gets a_{pos}\).
      • Увеличиваем счетчик: \(count \gets count + 1\).
  3. Проверка результата:

    • Если \(pos = n\): возвращаем \(count\).
    • Иначе (если \(pos \in visited\)): возвращаем \(-1\) (робот зациклился).
  • Максимальное количество шагов не превосходит \(n\), так как после \(n\) шагов робот гарантированно войдет в цикл (по принципу Дирихле).
  • Использование множества \(visited\) позволяет детектировать циклы за \(\mathcal{O}(1)\) на каждом шаге.
  • Алгоритм имеет временную сложность \(\mathcal{O}(n)\) и пространственную сложность \(\mathcal{O}(n)\).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
n = int(input())
a = list(map(int, input().split())) 

cur_pos = 1
steps = 0

while cur_pos != n:
    steps += 1
    cur_pos = a[cur_pos - 1]
    if steps > n: 
        steps = -1
        break

print(steps)
Задача 1.3.(20 баллов)
Сборка робота

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 1 с.

Ограничение по памяти: 256 Мбайт.

Условие

Как известно, чтобы собрать робота, надо его составить из трех частей: верхней (головы), средней (туловища) и нижней (ног).

У вас есть \(n\) деталей каждого из трех типов. Размер \(i\)-й детали, которую можно использовать в качестве верхней части робота, равен \(a_i\). Размер \(i\)-й детали, которую можно использовать в качестве средней части робота, равен \(b_i\). Наконец, размер \(i\)-й детали, которую можно использовать в качестве нижней части робота, равен \(c_i\).

Для того чтобы построенный робот правильно работал, необходимо соблюсти следующие условия:

  • размер средней части должен быть строго больше, чем размер верхней части;
  • размер нижней части должен быть строго больше, чем размер средней части.

Вам стало интересно, сколько существует различных способов построить робота, удовлетворяющего описанным условиям. Два способа считаются различными, если хотя бы одна из трех частей робота в них различается.

Формат входных данных

Первая строка содержит одно целое число \(n\) (\(1 \leqslant n \leqslant 100000\)) — количество деталей каждого из трех типов.

Вторая строка содержит \(n\) целых чисел \(a_1, a_2, \ldots, a_n\) (\(1 \leqslant a_i \leqslant 10^9\)) — размеры деталей, которые можно использовать в качестве верхней части робота.

Третья строка содержит \(n\) целых чисел \(b_1, b_2, \ldots, b_n\) (\(1 \leqslant b_i \leqslant 10^9\)) — размеры деталей, которые можно использовать в качестве средней части робота.

Четвертая строка содержит \(n\) целых чисел \(c_1, c_2, \ldots, c_n\) (\(1 \leqslant c_i \leqslant 10^9\)) — размеры деталей, которые можно использовать в качестве нижней части робота.

Формат выходных данных

Выведите одно целое число — количество различных способов построить робота, удовлетворяющего описанным условиям.

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
2
1 5
2 4
3 6
3
2
3
1 1 1
2 2 2
3 3 3
27
3
6
3 14 159 2 6 53
58 9 79 323 84 6
2643 383 2 79 50 288
87

Примечания

В первом примере можно составить трех различных роботов:

  • верхняя часть: первая деталь, средняя часть: первая деталь, нижняя часть: первая деталь;
  • верхняя часть: первая деталь, средняя часть: первая деталь, нижняя часть: втора деталь;
  • верхняя часть: первая деталь, средняя часть: втора деталь, нижняя часть: втора деталь.

Решение

Задача заключается в подсчете количества троек \((i, j, k)\) таких, что \(A_i < B_j < C_k\). Если зафиксировать \(j\), то искомое количество будет равно произведению количества \(i\), для которых \(A_i < B_j\), и количества \(k\), для которых \(B_j < C_k\).

Таким образом, для каждого \(j\) можно подсчитать количество подходящих \(i\) и \(k\), перемножить их и сложить результаты.

Как же подсчитать количество \(i\) и \(k\)? Если просто перебирать все элементы массива, то сложность будет \(\mathcal{O}(N^2)\), что неприемлемо.

Предварительно отсортируем массивы \(A\) и \(C\). Тогда количество \(i\) и \(k\) можно найти с помощью бинарного поиска. В C++ для этого удобно использовать стандартные функции lower_bound и upper_bound.

Итоговая временная сложность составит \(\mathcal{O}(N \log N)\), что является приемлемым.

Пример программы-решения

Ниже представлено решение на языке Python.

Python
import bisect
 
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = list(map(int, input().split()))
 
a.sort()
b.sort()
c.sort()
 
cnt = 0
 
for i in range(n):
    p = bisect.bisect_left(a, b[i])
    q = bisect.bisect_right(c, b[i])
    q = n - q
    cnt += p * q
 
print(cnt)

Задача 1.4.(22 балла)
Две матрицы

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 3 с.

Ограничение по памяти: 256 Мбайт.

Условие

Даны матрица \(A\) с \(H_1\) строками и \(W_1\) столбцами, а также матрица \(B\) с \(H_2\) строками и \(W_2\) столбцами.

Для всех целочисленных пар \((i, j)\) таких, что \(1 \leqslant i \leqslant H_1\) и \(1 \leqslant j \leqslant W_1\), элемент в \(i\)-й строке и \(j\)-м столбце матрицы \(A\) обозначается как \(A_{i,j}\).

Для всех целочисленных пар \((i, j)\) таких, что \(1 \leqslant i \leqslant H_2\) и \(1 \leqslant j \leqslant W_2\), элемент в \(i\)-й строке и \(j\)-м столбце матрицы \(B\) обозначается как \(B_{i,j}\).

Вы можете выполнять следующие операции над матрицей \(A\) любое количество раз (возможно, ноль) в любом порядке:

  • выбрать произвольную строку матрицы \(A\) и удалить ее;
  • выбрать произвольный столбец матрицы \(A\) и удалить его.

Определите, возможно ли сделать матрицу \(A\) равной матрице \(B\).

Формат входных данных

Первая строка содержит два целых числа: \(H_1\) (количество строк матрицы \(A\)) и \(W_1\) (количество столбцов матрицы \(A\)), где \((1 \leqslant H_1, W_1 \leqslant 10)\).

Следующие \(H_1\) строк описывают матрицу \(A\):

  • каждая строка содержит \(W_1\) целых чисел, разделенных пробелами;
  • каждый элемент матрицы \(A\) удовлетворяет условию \(1 \leqslant A_{i,j} \leqslant 10^9\).

Затем идет строка с двумя целыми числами: \(H_2\) (количество строк матрицы \(B\)) и \(W_2\) (количество столбцов матрицы \(B\)), где \((1 \leqslant H_2, W_2 \leqslant 10)\).

Следующие \(H_2\) строк описывают матрицу \(B\):

  • каждая строка содержит \(W_2\) целых чисел, разделенных пробелами;
  • каждый элемент матрицы \(B\) удовлетворяет условию \(1 \leqslant B_{i,j} \leqslant 10^9\).

Все значения во входных данных являются целыми числами.

Формат выходных данных

Выведите Yes, если возможно сделать матрицу \(A\) равной матрице \(B\); в противном случае выведите No.

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
4 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
2 3
6 8 9
16 18 19
Yes
2
3 3
1 1 1
1 1 1
1 1 1
1 1
2
No

Решение

Вместо того чтобы удалять строки и столбцы по одному, как в исходной постановке задачи, можно рассмотреть следующую операцию, выполняемую ровно один раз: «выбрать некоторые (возможно, ни одной) строки и столбцы исходной матрицы \(A\) и удалить выбранные строки и столбцы одновременно».

Например, для следующей матрицы \(A\), приведенной в примере 1, \[\begin{matrix} 1 &2 &3 &4 &5\\ 6 &7 &8 &9 &10\\ 11 &12 &13 &14 &15\\ 16 &17 &18 &19 &20 \end{matrix}\] можно выбрать первую строку, третью строку, второй столбец и пятый столбец и удалить их одновременно, чтобы получить следующую матрицу \(B\), приведенную в примере 1: \[\begin{matrix} 6 &8 &9\\ 16 &18 &19 \end{matrix}\]

Чтобы определить, можно ли сделать матрицу \(A\) равной матрице \(B\) с помощью таких операций, достаточно перебрать все \(2^{H_1}\) способов выбора «удалять ли каждую из \(H_1\) строк» и все \(2^{W_1}\) способов выбора «удалять ли каждый из \(W_1\) столбцов» (всего \(2^{(H_1 + W_1)}\) способов) и проверить, делает ли какой-либо из них матрицу \(A\) равной матрице \(B\).

Перебор всех способов

Для перебора всех \(2^{(H_1 + W_1)}\) способов выбора строк и столбцов можно использовать метод битового перебора (bit brute-forcing), который опишем ниже:

  • Каждый способ выбора «удалять ли каждую из \(H_1\) строк» представляется \(H_1\)-битовым двоичным неотрицательным числом \(X\), где:

    • Для \(i = 0, 1, 2, \dots, H_1 - 1\):

      • Если \(i\)-я строка удаляется, то \(i\)-й бит (считая с младшего разряда) числа \(X\) равен \(1\).
      • Если \(i\)-я строка не удаляется, то \(i\)-й бит равен \(0\).
  • Например, выбор удаления первой и третьей строк из 5 строк может быть представлен числом \(00101\) в двоичной системе. Таким образом, все \(2^{H_1}\) способов выбора строк могут быть представлены числами \(000\ldots 00\), \(000\ldots 01\), \(\ldots\), \(111\ldots 11\) в двоичной системе или числами \(0, 1, \ldots, 2^{H_1} - 1\) в десятичной системе.
  • Аналогично способы выбора «удалять ли каждый из \(W_1\) столбцов» могут быть представлены числами \(0, 1, \dots, 2^{W_1} - 1\).

Реализация перебора

Таким образом можно перебрать все комбинации способов выбора строк и столбцов с помощью двойного вложенного цикла, где:

  • первый цикл перебирает способы выбора строк: \(0, 1, \ldots, 2^{H_1} - 1\);
  • второй цикл перебирает способы выбора столбцов: \(0, 1, \ldots, 2^{W_1} - 1\).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
h1, w1 = map(int, input().split())
a = [list(map(int, input().split())) for _ in range(h1)]

h2, w2 = map(int, input().split())
b = [list(map(int, input().split())) for _ in range(h2)]

for i in range(1 << h1):
    for j in range(1 << w1):
        hvec = []
        wvec = []
        for k in range(1, h1 + 1):
            if (i & (1 << (k - 1))) == 0:
                hvec.append(k)
        for k in range(1, w1 + 1):
            if (j & (1 << (k - 1))) == 0:
                wvec.append(k)
        if len(hvec) != h2 or len(wvec) != w2:
            continue
        
        match = True
        for k in range(1, h2 + 1):
            for l in range(1, w2 + 1):
                if a[hvec[k - 1] - 1][wvec[l - 1] - 1] != b[k - 1][l - 1]:
                    match = False
                    break
            if not match:
                break
        if match:
            print("Yes")
            exit()

print("No")
Задача 1.5.(25 баллов)
Хитрый пароль

Имя входного файла: стандартный ввод или input.txt.

Имя выходного файла: стандартный вывод или output.txt.

Ограничение по времени выполнения программы: 1 с.

Ограничение по памяти: 256 Мбайт.

Условие

В качестве пароля дан клетчатый прямоугольник, каждый квадрат (\(1 \times 1\)) которого раскрашен в какой-то свой цвет.

Чтобы расшифровать пароль, требуется подсчитать количество прямоугольников, раскрашенных ровно в один цвет.

Формат входных данных

В первой строке даны два числа \(n\) и \(m\) (\(1 \leqslant n, m \leqslant 500\)) — длина и ширина прямоугольника.

В следующих \(n\) строках содержится по \(m\) символов — строчных латинских букв, отвечающих за цвет.

Формат выходных данных

Вывести пароль, зашифрованный в разноцветном прямоугольнике.

Тестовые данные

Номер тестаСтандартный вводСтандартный вывод
1
2 2
aa
aa
9
2
2 2
aa
ab
6

Решение

Постановка задачи

Дан прямоугольник размером \(n \times m\), где каждая ячейка раскрашена в один из цветов. Требуется подсчитать количество прямоугольников, раскрашенных ровно в один цвет.

Идея решения

Для каждой строки \(d\) и каждого столбца \(l\) перебираем все возможные прямоугольники, начиная с \((d, l)\). Для каждого прямоугольника находим минимальную высоту столбцов в диапазоне \([l, r]\) и добавляем ее к ответу.

Переменные

  • \(n\) — количество строк.
  • \(m\) — количество столбцов.
  • \(a\) — матрица размера \(n \times m\), содержащая цвета ячеек.
  • \(h\) — массив высот столбцов, где \(h[i]\) — количество подряд идущих ячеек одного цвета сверху в столбце \(i\).
  • \({ans}\) — итоговый ответ (количество одноцветных прямоугольников).

Алгоритм

  1. Инициализируем массив \(h\) единицами.
  2. Для каждой строки \(d\) от \(0\) до \(n-1\):

    • Для каждого столбца \(l\) от \(0\) до \(m-1\):

      • Инициализируем \(\text{min\_h} = h[l]\) и \(r = l\).
      • Пока \(r < m\) и \(a[d][r] = a[d][l]\):

        • Обновляем \(\text{min\_h} = \min(\text{min\_h}, h[r])\).
        • Добавляем \(\text{min\_h}\) к \({ans}\).
        • Увеличиваем \(r\) на \(1\).
    • Если \(d \neq n-1\), обновляем массив \(h\):

      • Для каждого столбца \(i\) от \(0\) до \(m-1\):

        • Если \(a[d][i] \neq a[d+1][i]\), сбрасываем \(h[i] = 1\).
        • Иначе увеличиваем \(h[i]\) на \(1\).
  3. Выводим \({ans}\).

Сложность

  • Временная сложность: \(\mathcal{O}(n \cdot m^2)\).
  • Пространственная сложность: \(\mathcal{O}(m)\).

Пример программы-решения

Ниже представлено решение на языке Python.

Python
n, m = map(int, input().split())
a = [input().strip() for _ in range(n)]
h = [1] * m  # Массив высот столбцов

ans = 0  # Итоговый ответ
for d in range(n):
    for l in range(m):
        min_h = h[l]  # Минимальная высота в текущем прямоугольнике
        r = l
        # Идём вправо, пока цвет ячеек совпадает
        while r < m and a[d][r] == a[d][l]:
            min_h = min(min_h, h[r])  # Обновляем минимальную высоту
            ans += min_h  # Добавляем количество прямоугольников
            r += 1
    # Обновляем высоты столбцов для следующей строки
    if d != n - 1:
        for i in range(m):
            if a[d][i] != a[d + 1][i]:
                h[i] = 1  # Сбрасываем высоту, если цвет меняется
            else:
                h[i] += 1  # Увеличиваем высоту, если цвет совпадает
print(ans)
text slider background image text slider background image
text slider background image text slider background image text slider background image text slider background image