Полигон YMLSYMLS PolygonТашкент · 2026Tashkent · 2026
до попыткиuntil the attempt —
День 11 1 сентября, вторник АлгоритмыAlgorithms

Сложность и структуры данныхComplexity and Data Structures

Пять приёмов, превращающих «переберу все пары» в один проход, и дисциплина доводить приём до числаFive techniques that turn “I’ll try every pair” into a single pass—and the discipline to carry each technique through to a number

0% дня закрыто · решено задач 7 из 16

цель дня
RU

К вечеру ты по формулировке задачи за полминуты называешь приём — хеш-таблица, префиксные суммы, окно, бинарный поиск по ответу, разряды — и доводишь его до конкретного числа кодом в десять строк. Проверка — пять финальных задач ниже, третья из них под таймером.

EN

By evening, when you read a problem statement, you can name the technique within half a minute—hash table, prefix sums, sliding window, binary search on the answer, or bitwise reasoning—and turn it into a concrete number with ten lines of code. The check is the five final problems below; the third one is timed.

Самостоятельные задачи

К концу дня нужно уметь решать эти задачи самостоятельно, без подсказок.

Мост · что нужно вспомнить
RU

Вчера определитель $3\times3$ считался разложением по строке. Это разложение для матрицы $n\times n$ даёт $n!$ слагаемых, а метод Гаусса приводит ту же матрицу к треугольной за порядка $n^3$ действий. Ответ у обоих путей один, разница только в числе операций — и вчера она была вопросом аккуратности, а сегодня становится вопросом, дождёшься ли ты ответа вообще.

Из восьмого дня приходит формула Ньютона — Лейбница. Префиксные суммы — её дискретная копия: заводится накопитель $S_k$, и сумма на отрезке считается как разность значений накопителя на концах, ровно как $F(b) - F(a)$ вместо интеграла.

Из шестого дня — иерархия роста $\ln n \ll n^{a} \ll e^{n}$. Там она отвечала на вопрос, какое слагаемое главное в пределе. Сегодня та же иерархия отвечает на вопрос, сколько секунд будет работать программа, и разница между $\log n$ и $n$ измеряется не в буквах, а в часах.

EN

Yesterday, the determinant of a $3\times3$ matrix was computed by expanding along a row. For an $n\times n$ matrix, that expansion produces $n!$ terms, while Gaussian elimination reduces the same matrix to triangular form in about $n^3$ operations. Both routes give the same answer; the only difference is the number of operations—and yesterday that was a matter of neatness, whereas today it becomes a question of whether you will ever see the answer at all.

Day 8 contributes the Newton–Leibniz formula. Prefix sums are its discrete counterpart: define an accumulator $S_k$, and compute a segment sum as the difference between the accumulator values at the endpoints, exactly like $F(b) - F(a)$ in place of an integral.

From day 6 comes the growth hierarchy $\ln n \ll n^{a} \ll e^{n}$. There it answered which term dominates in the limit. Today the same hierarchy answers how many seconds a program will run, and the gap between $\log n$ and $n$ is measured not in letters but in hours.

Вспомни вслух, до открытия конспектов:

  1. Деление с остатком: $a = qk + r$, где $0 \le r < k$; два числа дают одинаковый остаток при делении на $k$ тогда и только тогда, когда их разность делится на $k$Division with remainder: $a = qk + r$, where $0 \le r < k$; two numbers have the same remainder modulo $k$ if and only if their difference is divisible by $k$
  2. Округление вверх $\lceil p/k\rceil$ — сколько раз надо взять по $k$, чтобы покрыть $p$Ceiling $\lceil p/k\rceil$—how many times you need to take $k$ to cover $p$
  3. Целая часть $\lfloor p/L\rfloor$ — сколько целых кусков длины $L$ помещается в $p$Floor $\lfloor p/L\rfloor$—how many whole pieces of length $L$ fit into $p$
  4. $\log_2 n$ — сколько раз $n$ делится пополам, пока не останется единица: $\log_2 1024 = 10$, $\log_2 10^{6} \approx 20$$\log_2 n$—how many times $n$ is halved before only one remains: $\log_2 1024 = 10$, $\log_2 10^{6} \approx 20$
  5. Двоичная запись: $n = b_k 2^{k} + \cdots + b_1 2 + b_0$, где каждое $b_i$ равно 0 или 1Binary representation: $n = b_k 2^{k} + \cdots + b_1 2 + b_0$, where every $b_i$ is 0 or 1
  6. Сумма степеней двойки: $2^{m-1} + 2^{m-2} + \cdots + 2 + 1 = 2^{m} - 1$, то есть строго меньше одного $2^{m}$Sum of powers of two: $2^{m-1} + 2^{m-2} + \cdots + 2 + 1 = 2^{m} - 1$, strictly less than one $2^{m}$
  7. Число пар из $m$ предметов: $\binom{m}{2} = \frac{m(m-1)}{2}$; число подотрезков массива длины $n$ равно $\frac{n(n+1)}{2}$Number of pairs chosen from $m$ objects: $\binom{m}{2} = \frac{m(m-1)}{2}$; the number of subarrays of an array of length $n$ is $\frac{n(n+1)}{2}$
  8. Из дня 8: $\int_a^b f(x)\,dx = F(b) - F(a)$ — значение накопителя в правом конце минус в левомFrom day 8: $\int_a^b f(x)\,dx = F(b) - F(a)$—the accumulator’s value at the right endpoint minus its value at the left
  9. Из дня 6: $\ln n \ll n^{a} \ll e^{n}$ при $n \to \infty$From day 6: $\ln n \ll n^{a} \ll e^{n}$ as $n \to \infty$

Повторение прошлых дней

Карточки возвращаются через 1, 2, 4, 7, 14 и 21 день в зависимости от того, насколько уверенно ты их вспомнил; «не помню» отправляет карточку в начало. Это часть разогрева, вместе с блоком «Мост».

Комбинаторика день 1 осталось 97
RU

Правило умножения: две оговорки, без которых оно не работает

EN

The multiplication rule: two qualifications without which it does not work

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

6 задач: подборка покрывает темы и микронавыки последнего учебного дня (10), а для каждой идеи выбирает наиболее сильный доступный уровень. Здесь отдельная попытка: решение в исходном дне не подставляется. Сначала назови тему вслух, затем решай.

Y1004Уровень YMLSЛиналуровень YMLS
RU

Найдите сумму всех значений параметра $a$, при которых система

$$\begin{cases} ax + y + z = 1 \\ x + ay + z = a \\ x + y + az = a^{2} \end{cases}$$

не имеет ни одного решения. (Если такое значение единственно, суммой считается оно само; если таких значений нет, ответ 0.)

EN

Find the sum of all values of the parameter $a$ for which the system

$$\begin{cases} ax + y + z = 1 \\ x + ay + z = a \\ x + y + az = a^{2} \end{cases}$$

has no solution. If there is only one such value, that value itself is the required sum; if there are no such values, enter 0.

Подсказка / Hint
RU

Определитель этой матрицы уже разложен на множители в задаче b1003. Дальше каждый его корень надо подставить в систему отдельно — обрати внимание, что правая часть тоже зависит от $a$.

EN

The determinant of this matrix was already factored in problem b1003. Substitute each root into the system separately, remembering that the right-hand side also depends on $a$.

Решение / Solution
RU

Шаг 1. Определитель. Матрица системы — та же, что в b1003, и её определитель равен

$$\det A = (a + 2)(a - 1)^2$$

Он обращается в ноль при $a = 1$ и при $a = -2$. При всех остальных $a$ решение существует и единственно — этот случай закрыт, и считать в нём нечего.

Шаг 2. Случай $a = 1$. Подставляем всюду, включая правые части $1$, $a$, $a^2$:

$$\begin{cases} x + y + z = 1 \\ x + y + z = 1 \\ x + y + z = 1 \end{cases}$$

Три одинаковых уравнения. После вычитаний остаются две нулевые строки: $\rank A = \rank[A\mid\mathbf{b}] = 1$, неизвестных три, свободных переменных $3 - 1 = 2$. Решений бесконечно много, и в ответ это значение не входит.

Шаг 3. Случай $a = -2$. Правая часть равна $(1,\ -2,\ 4)$:

$$\left(\begin{array}{ccc|c} -2 & 1 & 1 & 1 \\ 1 & -2 & 1 & -2 \\ 1 & 1 & -2 & 4\end{array}\right)$$

Сложим все три строки. В каждом столбце коэффициенты дают $-2 + 1 + 1 = 0$, поэтому слева получается $0 \cdot x + 0 \cdot y + 0 \cdot z$, а справа $1 - 2 + 4 = 3$:

$$0 = 3$$

Противоречие: $\rank A = 2$, а $\rank[A\mid\mathbf{b}] = 3$. Решений нет, и это значение в ответ входит.

Ответ: подходит только $a = -2$, сумма равна $-2$.

Три ловушки этой задачи

Первая: сдать сумму корней определителя, то есть $1 + (-2) = -1$. Это ответ на другой вопрос — «при каких $a$ решение не единственно».

Вторая: забыть, что правая часть тоже зависит от $a$. При $a = 1$ она превращается в $(1,1,1)$, и именно поэтому система оказывается совместной; при правой части $(1,2,3)$ ответ был бы другим.

Третья: увидев кратный корень $(a-1)^2$, решить, что «двойной корень — двойное вырождение — точно нет решений». Кратность говорит только о том, насколько сильно падает ранг матрицы (здесь до единицы), и ничего не говорит о совместности. Совместность решается сравнением рангов, и ничем другим.

EN

Step 1. Determinant. The coefficient matrix is the same as in b1003, and its determinant is

$$\det A = (a + 2)(a - 1)^2$$

It vanishes for $a = 1$ and $a = -2$. For every other value of $a$, the solution exists and is unique.

Step 2. The case $a = 1$. Substitute into every occurrence of $a$, including the right-hand side entries $1$, $a$, and $a^2$:

$$\begin{cases} x + y + z = 1 \\ x + y + z = 1 \\ x + y + z = 1 \end{cases}$$

These are three identical equations. Row subtraction leaves two zero rows: $\rank A = \rank[A\mid\mathbf{b}] = 1$. There are three unknowns and $3 - 1 = 2$ free variables, so there are infinitely many solutions. This value is not included.

Step 3. The case $a = -2$. The right-hand side is $(1,\ -2,\ 4)$:

$$\left(\begin{array}{ccc|c} -2 & 1 & 1 & 1 \\ 1 & -2 & 1 & -2 \\ 1 & 1 & -2 & 4\end{array}\right)$$

Add all three rows. In each coefficient column the sum is $-2 + 1 + 1 = 0$, so the left-hand side becomes $0 \cdot x + 0 \cdot y + 0 \cdot z$, whereas the right-hand side is $1 - 2 + 4 = 3$:

$$0 = 3$$

This is a contradiction: $\rank A = 2$ while $\rank[A\mid\mathbf{b}] = 3$. There is no solution, so this value is included.

Answer: only $a = -2$ is valid, and the required sum is $-2$.

Three traps in this problem

First, one might submit the sum of the determinant's roots, $1 + (-2) = -1$. That answers a different question: “for which $a$ is the solution not unique?”

Second, one may forget that the right-hand side also depends on $a$. For $a = 1$, it becomes $(1,1,1)$, which is exactly why the system is consistent. With right-hand side $(1,2,3)$, the answer would differ.

Third, after seeing the repeated root $(a-1)^2$, one may reason that a “double root means double singularity, so there must be no solutions.” Multiplicity only describes how far the matrix rank drops here, to 1; it says nothing about consistency. Consistency is determined by comparing ranks.

уверенность1 — угадал, 5 — уверен полностью
S1001Уровень ШАДЛиналОлимпиада ШАД 2024, задача C «Дороги под Минском»
RU

В области дороги устроены так: любые два города соединяет ровно одна трасса, любые две трассы пересекаются ровно в одном городе, и на каждой трассе лежит не меньше двух городов (может быть и больше).

Всего трасс $n = 2071$. Сколько может быть городов? Если ответ единственный, укажите его.

EN

Roads in a region satisfy the following conditions: every pair of cities is connected by exactly one road, every pair of roads intersects in exactly one city, and every road contains at least two cities.

There are $n = 2071$ roads. How many cities can there be? If the answer is unique, give that value.

Подсказка / Hint
RU

Заведи матрицу «город — трасса» из нулей и единиц и посмотри, что означают произведения $AA^{T}$ и $A^{T}A$.

EN

Construct a zero-one city–road incidence matrix and interpret the products $AA^{T}$ and $A^{T}A$.

Решение / Solution
RU

Пусть $m$ — число городов. Введём матрицу инцидентности $A$ размера $m \times n$: $A_{ij} = 1$, если через город $i$ проходит трасса $j$, и 0 иначе.

Что означает $AA^{T}$. Элемент $(AA^T)_{ij}$ при $i \ne j$ — это число трасс, общих для городов $i$ и $j$. По условию оно равно 1. На диагонали стоит число трасс через город $i$; обозначим его $d_i$.

Покажем, что $d_i \ge 2$. Сначала $d_i \ge 1$, и это не пустая оговорка: на трассе лежит не меньше двух городов, значит городов всего не меньше двух, а любые два города соединены трассой — стало быть через каждый город проходит хотя бы одна трасса. Остаётся отбросить случай $d_i = 1$. Пусть через город $P$ проходит ровно одна трасса $L$. Любой другой город обязан иметь с $P$ ровно одну общую трассу, а она проходит через $P$, значит это $L$. Выходит, что все города лежат на $L$. Возьмём любую другую трассу $L'$ (трасс 2071, так что она есть): на ней не меньше двух городов, и все они лежат на $L$, то есть $|L \cap L'| \ge 2$ — противоречие с условием «ровно один общий город».

Значит $AA^{T} = J_m + D$, где $J_m$ — матрица из одних единиц, а $D$ — диагональная с элементами $d_i - 1 \ge 1$.

Что означает $A^{T}A$. Симметрично: $(A^TA)_{ij}$ при $i \ne j$ — число общих городов у трасс $i$ и $j$, оно равно 1; на диагонали стоит число городов на трассе $j$, и оно не меньше 2 по условию. Значит $A^{T}A = J_n + D'$ с положительной диагональной добавкой.

Обе матрицы невырождены — это факт из урока: для любого ненулевого $\mathbf{x}$ величина $\mathbf{x}^{T}(J + D)\mathbf{x} = (\sum_i x_i)^2 + \sum_i (d_i - 1)x_i^2$ строго положительна, поэтому нулевого вектора в ядре нет.

Финал. По тождеству из урока

$$\rank(AA^{T}) = \rank A = \rank(A^{T}A)$$

Матрица $AA^T$ имеет размер $m\times m$ и невырождена, значит её ранг равен $m$. Матрица $A^TA$ имеет размер $n \times n$ и невырождена, значит её ранг равен $n$. Но обе они равны $\rank A$. Следовательно $m = n = 2071$.

Ответ: ровно 2071 город — минимум и максимум совпадают.

Такая конфигурация действительно существует

Ответ «$m$ обязан равняться $n$» был бы пустым, если бы подходящих конфигураций не существовало вовсе. Вот явная: один город-центр, одна большая трасса, на которой лежат все остальные 2070 городов, и ещё 2070 коротких трасс, соединяющих центр с каждым из них по отдельности. Трасс ровно $1 + 2070 = 2071$, городов тоже 2071, и оба условия выполнены.

Что забрать на YMLS

Приём «закодируй конфигурацию матрицей и работай с рангом». Комбинаторная задача про города и дороги превратилась в утверждение о ранге — и решилась без единого перебора.

Тождество $\rank(A^{T}A) = \rank A$ стоит запомнить отдельно: оно же лежит в основе метода наименьших квадратов, то есть обучения линейной регрессии. Это ровно та причина, по которой линейная алгебра стоит в программе ML-школы.

EN

Let $m$ be the number of cities. Define the $m \times n$ incidence matrix $A$ by $A_{ij} = 1$ if road $j$ passes through city $i$, and $A_{ij}=0$ otherwise.

Interpret $AA^{T}$. For $i \ne j$, the entry $(AA^T)_{ij}$ is the number of roads shared by cities $i$ and $j$, which is 1 by assumption. The diagonal entry is the number of roads through city $i$; denote it by $d_i$.

We claim that $d_i \ge 2$. First, $d_i \ge 1$. This is not vacuous: every road contains at least two cities, so there are at least two cities in total; every pair of cities is joined by a road, hence at least one road passes through each city. It remains to exclude $d_i = 1$. Suppose exactly one road $L$ passes through a city $P$. Every other city must share exactly one road with $P$, and that road passes through $P$, so it must be $L$. Thus all cities lie on $L$. Now take any other road $L'$; one exists because there are 2071 roads. It contains at least two cities, all of which lie on $L$, so $|L \cap L'| \ge 2$, contradicting the condition that two roads share exactly one city.

Therefore $AA^{T} = J_m + D$, where $J_m$ is the all-ones matrix and $D$ is diagonal with entries $d_i - 1 \ge 1$.

Interpret $A^{T}A$. Symmetrically, for $i \ne j$, $(A^TA)_{ij}$ is the number of cities shared by roads $i$ and $j$, equal to 1. A diagonal entry is the number of cities on road $j$, which is at least 2. Thus $A^{T}A = J_n + D'$ with a positive diagonal correction.

Both matrices are nonsingular. For every nonzero $\mathbf{x}$, $\mathbf{x}^{T}(J + D)\mathbf{x} = (\sum_i x_i)^2 + \sum_i (d_i - 1)x_i^2$ is strictly positive, so the kernel contains no nonzero vector.

Conclusion. By the identity

$$\rank(AA^{T}) = \rank A = \rank(A^{T}A)$$

The matrix $AA^T$ is a nonsingular $m\times m$ matrix, so its rank is $m$. The matrix $A^TA$ is a nonsingular $n \times n$ matrix, so its rank is $n$. Both ranks equal $\rank A$. Hence $m = n = 2071$.

Answer: exactly 2071 cities; the minimum and maximum coincide.

Such a configuration really exists

The conclusion “$m$ must equal $n$” would be empty if no valid configuration existed. Here is one: take one central city, one long road containing all other 2070 cities, and 2070 additional short roads, each joining the center to one of those cities. There are exactly $1 + 2070 = 2071$ roads and 2071 cities, and both conditions are satisfied.

The YMLS takeaway

Use the technique “encode the configuration as a matrix and reason about rank.” A combinatorial problem about cities and roads became a rank statement and was solved without enumeration.

The identity $\rank(A^{T}A) = \rank A$ is worth memorizing. It also underlies the least-squares method used to train linear regression models, which is exactly why linear algebra is part of the ML school curriculum.

уверенность1 — угадал, 5 — уверен полностью
B1006БазаЛиналавторская
RU

Найдите сумму всех значений параметра $a$, при которых система

$$\begin{cases} x + y + z = 1 \\ 2x + 3y + az = 3 \\ x + ay + 3z = 3 \end{cases}$$

имеет бесконечно много решений. (Если такое значение единственно, суммой считается оно само.)

EN

Find the sum of all values of the parameter $a$ for which the system

$$\begin{cases} x + y + z = 1 \\ 2x + 3y + az = 3 \\ x + ay + 3z = 3 \end{cases}$$

has infinitely many solutions. If there is only one such value, that value itself is the required sum.

Подсказка / Hint
RU

Корней у определителя два, и ведут они себя по-разному. Для каждого сравни ранг матрицы системы с рангом расширенной матрицы.

EN

The determinant has two roots, and they behave differently. For each root, compare the rank of the coefficient matrix with the rank of the augmented matrix.

Решение / Solution
RU

Шаг 1. Определитель. Раскладываем по первой строке:

$$\det\begin{pmatrix} 1 & 1 & 1 \\ 2 & 3 & a \\ 1 & a & 3\end{pmatrix} = (9 - a^2) - (6 - a) + (2a - 3) = -a^2 + 3a = -a(a - 3)$$

Проверка подстановкой $a = 1$: исходный определитель равен $1(9-1) - 1(6-1) + 1(2-3) = 8 - 5 - 1 = 2$, и формула даёт $-1\cdot(-2) = 2$ ✓.

При $a \ne 0$ и $a \ne 3$ решение единственно. Разбираем два корня.

Шаг 2. Случай $a = 0$.

$$\left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 2 & 3 & 0 & 3 \\ 1 & 0 & 3 & 3\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & -2 & 1 \\ 0 & -1 & 2 & 2\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & -2 & 1 \\ 0 & 0 & 0 & 3\end{array}\right)$$

Последняя строка означает $0 = 3$: $\rank A = 2$, а $\rank[A\mid\mathbf{b}] = 3$. Решений нет, значение не подходит.

Шаг 3. Случай $a = 3$.

$$\left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 2 & 3 & 3 & 3 \\ 1 & 3 & 3 & 3\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 0 & 2 & 2 & 2\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0\end{array}\right)$$

Строка $0 = 0$: оба ранга равны 2, неизвестных три, свободных переменных $3 - 2 = 1$. Решений бесконечно много — они образуют прямую $(x, y, z) = (0,\ 1 - t,\ t)$. Значение подходит.

Ответ: подходит только $a = 3$, сумма равна 3.

Что здесь тренируется

Определитель обнулился дважды, а исходы получились разные. Никакого признака, позволяющего сказать заранее, какой корень «пустой», а какой «бесконечный», не существует: оба раза нужен Гаусс с числами. В финале y1004 вопрос задан про другой исход, и если разбор не сделан, ответ будет взят не тот.

Сравни матрицу коэффициентов с эталонной из урока: она отличается ровно одним элементом — в первой строке $-z$ заменено на $+z$. Определитель при этом меняется целиком, с $6 - a - a^{2}$ на $3a - a^{2}$, и корни вместо $2$ и $-3$ становятся $0$ и $3$. Отсюда правило: определитель с параметром пересчитывается заново при любой правке условия, даже если матрица «та же самая».

EN

Step 1. Determinant. Expand along the first row:

$$\det\begin{pmatrix} 1 & 1 & 1 \\ 2 & 3 & a \\ 1 & a & 3\end{pmatrix} = (9 - a^2) - (6 - a) + (2a - 3) = -a^2 + 3a = -a(a - 3)$$

Check by substituting $a = 1$: the original determinant is $1(9-1) - 1(6-1) + 1(2-3) = 8 - 5 - 1 = 2$, while the formula gives $-1\cdot(-2) = 2$ ✓.

For $a \ne 0$ and $a \ne 3$, the solution is unique. Consider the two roots separately.

Step 2. The case $a = 0$.

$$\left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 2 & 3 & 0 & 3 \\ 1 & 0 & 3 & 3\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & -2 & 1 \\ 0 & -1 & 2 & 2\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & -2 & 1 \\ 0 & 0 & 0 & 3\end{array}\right)$$

The last row states $0 = 3$: $\rank A = 2$ whereas $\rank[A\mid\mathbf{b}] = 3$. There is no solution, so this value is not valid.

Step 3. The case $a = 3$.

$$\left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 2 & 3 & 3 & 3 \\ 1 & 3 & 3 & 3\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 0 & 2 & 2 & 2\end{array}\right) \to \left(\begin{array}{ccc|c} 1 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0\end{array}\right)$$

The last row states $0 = 0$. Both ranks equal 2, there are three unknowns, and there is $3 - 2 = 1$ free variable. Thus there are infinitely many solutions, forming the line $(x, y, z) = (0,\ 1 - t,\ t)$. This value is valid.

Answer: only $a = 3$ is valid, so the sum is 3.

What this problem tests

The determinant vanishes for two parameter values, but the outcomes differ. There is no shortcut that reveals in advance which root gives no solution and which gives infinitely many; numerical Gaussian elimination must be carried out in both cases. Problem y1004 asks about the other outcome, and without carrying out the analysis it is easy to choose the wrong root.

Compare this coefficient matrix with the model example from the lesson. It differs in exactly one entry: $-z$ in the first row has become $+z$. The determinant changes completely, from $6 - a - a^{2}$ to $3a - a^{2}$, and the roots change from $2,-3$ to $0,3$. Therefore, a determinant involving a parameter must be recomputed after any change to the problem, even if the matrix looks “almost the same.”

уверенность1 — угадал, 5 — уверен полностью
Y1002Уровень YMLSЛиналуровень YMLS · по мотивам ШАД 2024
RU

Вычислите определитель матрицы

$$\begin{pmatrix} 4 & -1 & -1 & 0 \\ -1 & 4 & 0 & -1 \\ -1 & 0 & 4 & -1 \\ 0 & -1 & -1 & 4 \end{pmatrix}$$
EN

Evaluate the determinant of the matrix

$$\begin{pmatrix} 4 & -1 & -1 & 0 \\ -1 & 4 & 0 & -1 \\ -1 & 0 & 4 & -1 \\ 0 & -1 & -1 & 4 \end{pmatrix}$$
Подсказка / Hint
RU

Разложение по строке — это четыре определителя $3\times3$ и почти гарантированная знаковая ошибка. Посчитай вместо этого сумму элементов в каждой строке.

EN

Expanding along a row produces four $3\times3$ determinants and makes a sign error very likely. Instead, calculate the sum of the entries in each row.

Решение / Solution
RU

Сумма элементов одинакова во всех четырёх строках и равна 2. Значит первый ход — прибавить к первому столбцу три остальных: определитель от этого не меняется, а весь первый столбец становится постоянным.

$$\begin{vmatrix} 4 & -1 & -1 & 0 \\ -1 & 4 & 0 & -1 \\ -1 & 0 & 4 & -1 \\ 0 & -1 & -1 & 4 \end{vmatrix} = \begin{vmatrix} 2 & -1 & -1 & 0 \\ 2 & 4 & 0 & -1 \\ 2 & 0 & 4 & -1 \\ 2 & -1 & -1 & 4 \end{vmatrix} = 2\begin{vmatrix} 1 & -1 & -1 & 0 \\ 1 & 4 & 0 & -1 \\ 1 & 0 & 4 & -1 \\ 1 & -1 & -1 & 4 \end{vmatrix}$$

Теперь вычитаем первую строку из трёх остальных — под ведущей единицей появляются нули:

$$= 2\begin{vmatrix} 1 & -1 & -1 & 0 \\ 0 & 5 & 1 & -1 \\ 0 & 1 & 5 & -1 \\ 0 & 0 & 0 & 4 \end{vmatrix} = 2\begin{vmatrix} 5 & 1 & -1 \\ 1 & 5 & -1 \\ 0 & 0 & 4\end{vmatrix}$$

В оставшемся определителе последняя строка почти пустая — раскладываем по ней:

$$= 2 \cdot 4 \begin{vmatrix} 5 & 1 \\ 1 & 5\end{vmatrix} = 2\cdot4\cdot24 = 192$$

Ответ: 192. Четыре определителя $3\times3$ не понадобились: вся работа свелась к одному сложению столбцов и трём вычитаниям строк.

Откуда взялась эта матрица

Это в точности матрица системы из олимпиадной задачи ШАД 2024 «Май в Квадратленде»: температура каждой внутренней клетки равна среднему арифметическому соседей.

Там спрашивали не определитель, а можно ли однозначно восстановить внутренние температуры по граничным. Ответ — да, и доказывается он без всяких вычислений: у матрицы строгое диагональное преобладание ($4 > 1 + 1 + 0$ в каждой строке), а такие матрицы невырождены, значит решение существует и единственно.

Умение сказать «матрица обратима, потому что диагональ доминирует» экономит на экзамене пять минут и производит сильное впечатление на собеседовании.

EN

The entries in each of the four rows have the same sum, 2. Therefore the first move is to add the other three columns to the first. This does not change the determinant and makes the entire first column constant.

$$\begin{vmatrix} 4 & -1 & -1 & 0 \\ -1 & 4 & 0 & -1 \\ -1 & 0 & 4 & -1 \\ 0 & -1 & -1 & 4 \end{vmatrix} = \begin{vmatrix} 2 & -1 & -1 & 0 \\ 2 & 4 & 0 & -1 \\ 2 & 0 & 4 & -1 \\ 2 & -1 & -1 & 4 \end{vmatrix} = 2\begin{vmatrix} 1 & -1 & -1 & 0 \\ 1 & 4 & 0 & -1 \\ 1 & 0 & 4 & -1 \\ 1 & -1 & -1 & 4 \end{vmatrix}$$

Now subtract the first row from each of the other three, producing zeros below the leading 1:

$$= 2\begin{vmatrix} 1 & -1 & -1 & 0 \\ 0 & 5 & 1 & -1 \\ 0 & 1 & 5 & -1 \\ 0 & 0 & 0 & 4 \end{vmatrix} = 2\begin{vmatrix} 5 & 1 & -1 \\ 1 & 5 & -1 \\ 0 & 0 & 4\end{vmatrix}$$

The last row of the remaining determinant is almost entirely zero, so expand along it:

$$= 2 \cdot 4 \begin{vmatrix} 5 & 1 \\ 1 & 5\end{vmatrix} = 2\cdot4\cdot24 = 192$$

Answer: 192. There was no need to evaluate four $3\times3$ determinants: the entire calculation reduced to one column addition and three row subtractions.

Where this matrix comes from

This is exactly the coefficient matrix from the 2024 YSDA olympiad problem “May in Squareland,” where the temperature of each interior cell equals the arithmetic mean of the temperatures of its neighbors.

That problem asks whether the interior temperatures can be recovered uniquely from the boundary values, not for the determinant. The answer is yes, and it can be proved without any calculation: the matrix is strictly diagonally dominant ($4 > 1 + 1 + 0$ in each row), so it is nonsingular and the solution exists and is unique.

Recognizing that “the matrix is invertible because its diagonal dominates” can save five minutes on an exam and is a strong observation in an interview.

уверенность1 — угадал, 5 — уверен полностью
Y1001Уровень YMLSЛиналпо YMLS Practice Problem 3, Q1 · условие уточнено
RU

В $\mathbb{R}^{2}$ векторы $u$, $v$, $w$ удовлетворяют условиям: $|u| = |v| = \sqrt5$, $u \cdot v = 3$ (угол острый), $|w| = \sqrt{37}$, $u \cdot w = 13$, и система $\{u, v, w\}$ линейно зависима.

Известно также, что $v$ и $w$ отклонены от $u$ в одну и ту же сторону: они лежат в одной полуплоскости относительно прямой $\{t\,u : t \in \mathbb{R}\}$.

Найдите $v \cdot w$. Ответ с четырьмя знаками после запятой.

EN

Vectors $u$, $v$, and $w$ in $\mathbb{R}^{2}$ satisfy $|u| = |v| = \sqrt5$, $u \cdot v = 3$ (so the angle is acute), $|w| = \sqrt{37}$, $u \cdot w = 13$, and the set $\{u, v, w\}$ is linearly dependent.

It is also known that $v$ and $w$ lie on the same side of the line spanned by $u$: they lie in the same open half-plane bounded by the line $\{t\,u : t \in \mathbb{R}\}$.

Find $v \cdot w$. Give your answer to four decimal places.

Подсказка / Hint
RU

Составь таблицу всех попарных скалярных произведений с неизвестной $X = v\cdot w$ и приравняй её определитель нулю. Корней окажется два — разделяет их условие про полуплоскость.

EN

Form the matrix of all pairwise inner products, using $X = v\cdot w$ for the unknown entries, and set its determinant equal to zero. There will be two roots; the half-plane condition distinguishes them.

Решение / Solution
RU

Обозначим $X = v \cdot w$ и составим матрицу Грама — таблицу всех попарных скалярных произведений. На диагонали стоят квадраты длин:

$$G = \begin{pmatrix} 5 & 3 & 13 \\ 3 & 5 & X \\ 13 & X & 37 \end{pmatrix}$$

Линейная зависимость равносильна $\det G = 0$. Раскрывая определитель:

$$-5X^{2} + 78X - 253 = 0 \;\Longleftrightarrow\; 5X^{2} - 78X + 253 = 0$$$$X = \frac{78 \pm \sqrt{6084 - 5060}}{10} = \frac{78 \pm 32}{10} \;\Longrightarrow\; X = 11 \quad \text{или} \quad X = 4.6$$

Какой корень выбрать. Оба корня геометрически реализуемы, так что выбор делает не алгебра, а условие про полуплоскость. Повернём систему координат так, чтобы $u$ смотрел вдоль первой оси: $u = (\sqrt5,\, 0)$. Поворот не меняет ни длин, ни скалярных произведений, поэтому все условия задачи сохраняются.

  • Из $u \cdot w = 13$ первая координата: $\sqrt5\,w_1 = 13$, то есть $w_1 = 13/\sqrt5$. Тогда из $|w|^2 = 37$ вторая: $w_2^2 = 37 - \tfrac{169}{5} = \tfrac{16}{5}$, то есть $w_2 = \pm\tfrac{4}{\sqrt5}$.
  • Из $u \cdot v = 3$ точно так же $v_1 = 3/\sqrt5$, а из $|v|^2 = 5$ получаем $v_2^2 = 5 - \tfrac95 = \tfrac{16}{5}$, то есть $v_2 = \pm\tfrac{4}{\sqrt5}$.

Знак второй координаты — это и есть полуплоскость относительно прямой, натянутой на $u$. Условие «$v$ и $w$ по одну сторону» означает $v_2 w_2 > 0$, и тогда

$$v \cdot w = v_1 w_1 + v_2 w_2 = \frac{3}{\sqrt5}\cdot\frac{13}{\sqrt5} + \frac{16}{5} = \frac{39}{5} + \frac{16}{5} = 11$$

Противоположные знаки дали бы $\tfrac{39}{5} - \tfrac{16}{5} = 4.6$ — это ровно второй корень квадратного уравнения. Перебор всех четырёх сочетаний знаков даёт только два значения, $11$ и $4.6$, так что полуплоскость отсекает лишнее однозначно.

Проверка другим путём. При $v_2 w_2 > 0$ вектор $w$ оказывается равен $2u + v$: первая координата $2\sqrt5 + 3/\sqrt5 = 13/\sqrt5$, вторая $0 + 4/\sqrt5$ — совпадает покоординатно. Значит $v \cdot w = 2(u\cdot v) + (v\cdot v) = 6 + 5 = 11$, и это то же число, полученное без координат вовсе.

Ответ: 11.0000. Это совпадает с официальным ответом. В исходной формулировке YMLS дополнительного условия о полуплоскости нет, поэтому значение $4.6000$ там тоже геометрически реализуемо; здесь добавленное условие однозначно оставляет $11.0000$.

Почему это главная задача блока

Матрица Грама почти не встречается в стандартных курсах первого курса, но стоит прямо в официальных материалах YMLS. Критерий $\det G = 0$ надо знать так же твёрдо, как теорему Пифагора.

И отдельно: квадратное уравнение даёт два корня, и оба могут быть геометрически реализуемы. Умение выбрать нужный по дополнительному условию — часть задачи, а не формальность.

EN

Let $X = v \cdot w$ and form the Gram matrix, the matrix of all pairwise inner products. Its diagonal entries are the squared norms:

$$G = \begin{pmatrix} 5 & 3 & 13 \\ 3 & 5 & X \\ 13 & X & 37 \end{pmatrix}$$

Linear dependence is equivalent to $\det G = 0$. Expanding the determinant gives

$$-5X^{2} + 78X - 253 = 0 \;\Longleftrightarrow\; 5X^{2} - 78X + 253 = 0$$$$X = \frac{78 \pm \sqrt{6084 - 5060}}{10} = \frac{78 \pm 32}{10} \;\Longrightarrow\; X = 11 \quad \text{or} \quad X = 4.6$$

Choose the root. Both roots can be realized geometrically, so the half-plane condition, not algebra, determines the answer. Rotate the coordinate system so that $u$ points along the first axis: $u = (\sqrt5,\, 0)$. Rotation preserves norms and inner products, so all conditions remain valid.

  • From $u \cdot w = 13$, the first coordinate satisfies $\sqrt5\,w_1 = 13$, so $w_1 = 13/\sqrt5$. Then $|w|^2 = 37$ gives $w_2^2 = 37 - \tfrac{169}{5} = \tfrac{16}{5}$, so $w_2 = \pm\tfrac{4}{\sqrt5}$.
  • Similarly, $u \cdot v = 3$ gives $v_1 = 3/\sqrt5$, and $|v|^2 = 5$ gives $v_2^2 = 5 - \tfrac95 = \tfrac{16}{5}$, so $v_2 = \pm\tfrac{4}{\sqrt5}$.

The sign of the second coordinate determines the half-plane relative to the line spanned by $u$. The condition that $v$ and $w$ lie on the same side means $v_2 w_2 > 0$, and then

$$v \cdot w = v_1 w_1 + v_2 w_2 = \frac{3}{\sqrt5}\cdot\frac{13}{\sqrt5} + \frac{16}{5} = \frac{39}{5} + \frac{16}{5} = 11$$

Opposite signs would give $\tfrac{39}{5} - \tfrac{16}{5} = 4.6$, exactly the second root of the quadratic. Checking all four sign combinations yields only the values $11$ and $4.6$, so the half-plane condition removes the extraneous choice unambiguously.

A second check. When $v_2 w_2 > 0$, we have $w = 2u + v$: the first coordinate is $2\sqrt5 + 3/\sqrt5 = 13/\sqrt5$, and the second is $0 + 4/\sqrt5$, matching coordinatewise. Thus $v \cdot w = 2(u\cdot v) + (v\cdot v) = 6 + 5 = 11$, the same value obtained without using coordinates.

Answer: 11.0000. This matches the official answer. The original YMLS statement does not include the half-plane condition, so $4.6000$ can also be realized geometrically there. The added condition in this version uniquely selects $11.0000$.

Why this is the central problem of the unit

Gram matrices rarely appear in standard first-year courses, but one occurs explicitly in the official YMLS materials. The criterion $\det G = 0$ should be known as reliably as the Pythagorean theorem.

Also remember that a quadratic equation gives two roots, and both may be geometrically realizable. Selecting the required one using an additional condition is part of the problem, not a formality.

уверенность1 — угадал, 5 — уверен полностью
W1001РазминкаЛиналразминка
RU

Вычислите $\det\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}$.

EN

Evaluate $\det\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}$.

Подсказка / Hint
RU

$ad - bc$.

EN

Use $ad - bc$.

Решение / Solution
RU$$1 \cdot 4 - 2 \cdot 3 = 4 - 6 = -2$$

Определитель не равен нулю, значит строки $(1,2)$ и $(3,4)$ линейно независимы, а система с такой матрицей имеет ровно одно решение при любой правой части.

EN$$1 \cdot 4 - 2 \cdot 3 = 4 - 6 = -2$$

The determinant is nonzero, so the rows $(1,2)$ and $(3,4)$ are linearly independent, and a system with this coefficient matrix has exactly one solution for every right-hand side.

уверенность1 — угадал, 5 — уверен полностью
зачем это сегодня
RU

Алгоритмический блок — это два часа из пяти на очном экзамене и целая секция с живым кодированием на собеседовании. Часть задач онлайн-этапа тоже программистские.

Но у сегодняшнего дня есть особенность, из-за которой его нельзя проходить как обычную тему по алгоритмам. Онлайн-этап принимает число, а не программу. Никто не проверит, за сколько операций ты его получил, и никто не даст частичный балл за верную идею. Значит навык дня двойной: узнать приём по формулировке — и довести его до конкретного числа на конкретных данных, ничего не сломав на границах.

Обычный совет для этого блока — решать по одной-две задачи в день несколько месяцев подряд. Такого запаса времени у тебя нет, поэтому берём не объём, а покрытие шаблонов: пять приёмов, которые закрывают подавляющее большинство формулировок, и по три задачи возрастающей сложности на каждый.

EN

Algorithms take two of the five hours on the in-person exam and make up an entire live-coding section in an interview. Some online-stage problems are programming problems too.

But today has one feature that means you cannot study it like an ordinary algorithms topic. The online stage accepts a number, not a program. No one checks how many operations you used, and no one awards partial credit for a good idea. So today’s skill has two parts: recognize the technique from the wording, then carry it through to a concrete number on concrete data without breaking an edge case.

The usual advice for this block is to solve one or two problems a day for several months. You do not have that much time, so we optimize for pattern coverage, not volume: five techniques that cover the overwhelming majority of statements, with three problems of increasing difficulty for each one.

Навыки по порядку

Тема разбита на отдельные навыки от простого к сложному. Для каждого указаны тренировочные задачи.

  1. 1Ответ считается кодомThe answer is codeПереводишь условие в пять строк Python — множество, генератор с условием, куча размера $k$ — а по ограничению на размер входа заранее называешь, какая сложность пройдётTurn the statement into five lines of Python—a set, a conditional generator, a heap of size $k$—and use the input-size constraint to name the feasible complexity before you startW1101B1102Y1104
  2. 2Хеш-таблица «видел раньше»Hash table: “seen before”Вместо перебора пар держишь счётчик уже пройденного и на каждом шаге задаёшь ему ровно один вопрос; «найти» — множество, «посчитать» — счётчикInstead of enumerating pairs, keep a count of what you have already passed and ask it exactly one question at each step; “find” means a set, “count” means a counterB1101B1104Y1101
  3. 3Префиксные суммы и остаткиPrefix sums and remaindersСумму на отрезке берёшь разностью двух префиксов, а «делится на k» превращаешь в равенство остатков — и спрашиваешь про них тот же счётчик из предыдущего навыкаTake a segment sum as the difference of two prefixes, turn “divisible by k” into equal remainders, and ask the same counter from the previous skillB1103B1104Y1101
  4. 4Окно: правый конец ведёт, левый догоняетWindow: the right end leads, the left catches upТот же вопрос про подотрезки, но состояние — не число, а пара границ; сначала длина окна постоянна, потом её задаёт условие, а обе границы всегда идут только вперёдThe question is still about subarrays, but the state is a pair of boundaries rather than a number; first the window length is fixed, then the condition determines it, and both boundaries always move forwardW1103B1106Y1103
  5. 5Бинарный поиск по ответуBinary search on the answerКогда одним проходом не обойтись, ищешь не элемент массива, а само число ответа: пишешь предикат «годится ли $t$», проверяешь монотонность и режешь отрезок пополамWhen one pass is not enough, search for the answer itself rather than an array element: write the predicate “does $t$ work?”, check monotonicity, and halve the intervalW1104B1107Y1102
  6. 6Числа поразрядноBitwise numbersТот же перебор пар, но шаг смотрит на биты: XOR складывает разряды без переноса, а старший разряд перевешивает все младшие вместе взятые, и перебор превращается в спуск по разрядамIt is still pair enumeration in spirit, but each step looks at bits: XOR combines digits without carries, and the highest bit outweighs all lower bits together, turning enumeration into a descent through the bitsW1102B1105S1101

Расписание

0:00–0:20РазогревWarm-up Восемь карточек дня и все девять пунктов блока «Мост» вслух. Округление вверх и связь «одинаковый остаток — разность кратна» должны выговариваться без паузы: на них стоят два финала.Say the day’s eight cards and all nine points in the “Bridge” block out loud. You should be able to say the ceiling and the “same remainder means a divisible difference” connection without pausing: two finals depend on them.
0:20–1:40УрокLesson Каждый блок кода набирай руками и запускай. Читать код глазами бесполезно: на экзамене ты будешь его печатать, а печатают мышцы, а не понимание.Type and run every code block by hand. Reading code with your eyes is useless here: in the exam you will type it, and typing is done by muscles, not by understanding alone.
1:40–3:20ЗадачиProblems По ступеням 1 → 4. Перед каждой задачей вслух: приём, сложность, ограничение. Ступень 3 — пять мостов, четыре из них обязательные; пятый, b1105, ведёт к задаче ШАД.Follow levels 1 → 4. Before each problem, say aloud: technique, complexity, constraint. Level 3 has five bridges, four mandatory; the fifth, b1105, leads to the SHAD problem.
3:20–3:45Мини-тестMini-test y1103 под таймером, в режиме экзамена: подсказка и разбор закрыты, ответ вводится один раз.Do y1103 under a timer, in exam mode: hints and the walkthrough are closed, and you enter the answer only once.
3:45–4:00АудитAudit Критерии внизу страницы и журнал ошибок с разделением на два типа.Use the criteria at the bottom of the page and an error log that separates the two error types.

Урок

разбираем с нуля
RU

Вход: две программы, обе правильные

В массиве миллион чисел; сколько в нём пар с суммой 100? Наивный ход — два вложенных цикла: пар около $5\cdot10^{11}$, программа считает часами. Умный — один проход, на каждом шаге один вопрос счётчику: сколько раз уже встречалось $100 - x$; это $10^{6}$ шагов, доли секунды. Обе программы верны математически, но досчитает одна. Весь день про то, как за полминуты понять по формулировке, какая из двух у тебя в голове, и как вторую написать без ошибок на границах.

Python в объёме дня

a = [3, 1, 4, 1, 5]
a[0], a[-1], a[1:4]                 # 3 5 [1, 4, 1] — с нуля, правый конец не входит
sum(1 for v in a if v > 3)          # 2 — счёт по условию
sorted(a, reverse=True)[:3]         # [5, 4, 3]
7 // 2, 7 % 2, -(-7 // 2)           # 3 1 4 — нацело, остаток, округление ВВЕРХ
5 ^ 3, 5 >> 1, 5 & 1                # 6 2 1 — XOR, сдвиг вправо, младший бит
s = set(a); 3 in s                  # {1, 3, 4, 5}; True — только «есть или нет»
from collections import Counter
c = Counter(a); c[1], c[42]         # 2 0 — отсутствующий ключ даёт ноль, а не ошибку
import heapq; heapq.nlargest(3, a)  # [5, 4, 3] без полной сортировки
for i, v in enumerate(a): pass      # индекс и значение сразу

Две строки отсюда важны отдельно: -(-p // k) — округление вверх без модуля math (деление нацело округляет вниз), а Counter даёт ноль для отсутствующего ключа, поэтому приёмы ниже пишутся без проверки if key in d.

Сколько операций ты можешь себе позволить

Считать надо не секунды, а число операций: секунды зависят от машины, число операций — только от алгоритма и размера входа $n$.

Сложность$n = 10^{3}$$n = 10^{5}$$n = 10^{6}$
$O(n)$$10^{3}$$10^{5}$$10^{6}$
$O(n\log n)$$10^{4}$$1.7\cdot10^{6}$$2\cdot10^{7}$
$O(n^{2})$$10^{6}$$10^{10}$$10^{12}$

Ориентир: компилируемый язык делает порядка $10^{8}$ простых операций в секунду, Python — на порядок-полтора меньше. Значит $10^{10}$ операций это около двух минут даже в хорошем случае, а $10^{12}$ — около трёх часов.

Ограничение в условии — это подсказка про сложность

$n \le 10^{3}$ — квадратичный алгоритм пройдёт. $n \le 10^{6}$ — нужен один проход, сортировка или логарифм. $n \ge 10^{7}$ — только один проход. Читай ограничение до того, как придумывать решение: оно почти всегда называет приём.

СтруктураБыстроМедленно или нельзяКогда брать
listиндекс, добавление в конецпоиск значения — $O(n)$нужен порядок и индексы
setпроверка «есть ли», вставка — $O(1)$нет порядка и индексовнужен только факт наличия
dictпоиск по ключу, вставка — $O(1)$нет порядка по значениюнужно сопоставить ключу число
куча (heapq)достать минимум — $O(\log n)$искать произвольный элементнужны $k$ крайних из $n$

Множество и словарь платят за скорость памятью — в несколько раз больше, чем список. Формулировка для собеседования: «поиск за $O(1)$ в среднем, потому что хеш ведёт сразу в нужную ячейку; плата — память».

Приём 1. Хеш-таблица «видел раньше»

Two Sum. Есть ли в массиве пара с суммой target? Наивно — для каждого элемента искать пару справа, это все пары. Умно — держать множество seen уже пройденных и проверять target - x in seen: один проход вместо двух вложенных циклов. Вся идея в перемене вопроса: не «найдётся ли дальше», а «было ли раньше».

Если спрашивают, сколько таких пар, множество не годится: оно помнит факт, а не количество. Нужен счётчик:

from collections import Counter
seen = Counter(); cnt = 0
for x in a:
    cnt += seen[target - x]     # сколько подходящих уже было
    seen[x] += 1

«Найти пару» — множество, «посчитать пары» — счётчик. Перепутанная развилка даёт заниженный ответ без сигнала об ошибке, и она же решает исход финала y1101. Сам вопрос счётчику меняется от задачи к задаче: «сколько раз уже встречалось $10 - x$» в b1101, «сколько прежних префиксов равны $S_r - 36$» в b1104, «сколько прежних префиксов дают тот же остаток» в y1101. Вопрос разный, проход один и тот же.

Приём 2. Префиксные суммы

Заводим накопитель $S_0 = 0$, $S_k = a_1 + \cdots + a_k$ одним циклом pre.append(pre[-1] + v). Тогда сумма отрезка — одна разность, дословно как в формуле Ньютона — Лейбница: сумма элементов с индексами от $l$ до $r$ включительно равна $S_{r+1} - S_l$. Для $a = [4, 1, 6, 2, 5]$ выходит $S = [0, 4, 5, 11, 13, 18]$, и сумма элементов с индексами от 1 до 3 равна $S_4 - S_1 = 13 - 4 = 9$, то есть $1 + 6 + 2$.

Остатки — главный поворот темы. Сколько подотрезков имеют сумму, кратную $k$? Сумма отрезка это $S_r - S_l$, а по пункту блока «Мост» она делится на $k$ ровно тогда, когда $S_r$ и $S_l$ дают одинаковый остаток. Вопрос про отрезки стал вопросом про пары префиксов с равным остатком — а такие пары считает счётчик из приёма 1:

from collections import Counter
c = Counter({0: 1})        # пустой префикс тоже участвует
s = 0; total = 0
for v in a:
    s = (s + v) % k
    total += c[s]          # все прежние префиксы с тем же остатком
    c[s] += 1

Проверим руками: $a = [3, 1, 4, 1, 5]$, $k = 3$. Префиксы $[0, 3, 4, 8, 9, 14]$, остатки $[0, 0, 1, 2, 0, 2]$. Остаток 0 встретился трижды — это $\binom{3}{2} = 3$ пары, остаток 2 дважды — ещё одна, остаток 1 — ни одной. Итого 4, и перебор всех пятнадцати подотрезков даёт те же 4.

c[0] = 1 — не украшение

Пустой префикс $S_0 = 0$ обязан лежать в счётчике до начала цикла, иначе потеряются все подотрезки, начинающиеся с первого элемента. Код выглядит правильным, ответ просто занижен, и без разбора причину не видно. Это ошибка номер один темы.

Кадане — тот же вопрос к прошлым префиксам. Максимальная сумма подотрезка с правым концом $r$ равна $S_r - \min_{l < r} S_l$, поэтому хватает бегущего минимума вместо перебора пар. В обычной записи это две строки: cur = max(v, cur + v) и best = max(best, cur) при начальных best = cur = a[0], где cur — лучшая сумма подотрезка, кончающегося на текущем элементе, а выбор внутри max — решение «оставить левую границу или перенести её сюда». На массиве $[5, -2, -6, 7, -1, 4]$ значения cur идут $5, 3, -3, 7, 6, 10$, максимум 10 — это отрезок $[7, -1, 4]$, и перебор всех 21 подотрезка даёт то же. Начальное best = 0 вместо a[0] — главная ловушка приёма: на одних отрицательных числах такой код вернёт ноль.

Приём 3. Два указателя и окно

Встречное движение. На отсортированном массиве пара с заданной суммой ищется двумя указателями с концов: сумма мала — двигаем левый вправо, велика — правый влево. Это $O(n\log n)$ из-за сортировки, дороже хеш-множества, зато без лишней памяти.

Окно постоянной длины. Самый простой случай: длина окна задана числом, границы двигаются на каждом шаге вместе, а сумма нового окна берётся из старой за два действия — прибавить пришедший справа элемент, вычесть ушедший слева (w1103). Полный пересчёт стоил бы $O(nk)$, сдвиг стоит $O(n)$ при любой длине окна.

Окно переменной длины. Оба указателя идут в одну сторону: правый расширяет отрезок, левый догоняет, когда условие сломалось. Самый длинный подотрезок с суммой не больше 9 в массиве $[6, 1, 2, 3, 1, 7, 2, 4]$:

a = [6, 1, 2, 3, 1, 7, 2, 4]
s = 0; left = 0; best = 0
for right, v in enumerate(a):
    s += v
    while s > 9:                # условие сломалось — двигаем левую границу
        s -= a[left]; left += 1
    best = max(best, right - left + 1)
print(best)                     # 4

Ответ 4 — отрезок $[1, 2, 3, 1]$ с суммой 7; перебор всех 36 подотрезков даёт то же, но окно делает один проход.

Почему окно линейно

Каждый из двух указателей проходит массив ровно один раз и никогда не идёт назад, поэтому шагов не больше $2n$, сколько бы раз внутренний while ни срабатывал. Это же единственное, что можно сломать: стоит левой границе прыгнуть назад, как правильность и линейность исчезают одновременно.

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

Приём 4. Бинарный поиск по ответу

По отсортированному массиву элемент ищут делением пополам за $\log_2 n$ шагов. Но на экзамене чаще встречается другой поворот: ищут не элемент массива, а само число ответа. Признак — «минимальное такое, что» или «максимальное такое, что» плюс лёгкая проверка конкретного значения. Пример. Наименьшее целое $x$, у которого $x^{2} \ge 3000$. Предикат — это x * x >= 3000, и он монотонен: годится $x$ — годится и любое большее. Значит годные значения образуют луч, и нужна его левая граница.

lo, hi = 1, 3000                # hi заведомо годится
while lo < hi:
    mid = (lo + hi) // 2
    if mid * mid >= 3000: hi = mid      # годится — граница не правее mid
    else:                 lo = mid + 1  # не годится — mid точно мал
print(lo)                       # 55 за 12 шагов вместо 3000 проверок

Проверка соседа: $55^{2} = 3025 \ge 3000$, а $54^{2} = 2916 < 3000$ — значит 55 именно граница.

Шаблон запоминается дословно

while lo < hi, внутри hi = mid и lo = mid + 1, ответ в lo. Инвариант: hi всегда «годится», lo — левый край области поиска; отрезок каждый шаг строго укорачивается, поэтому зацикливания нет.

Для «максимальное такое, что» шаблон зеркальный: mid = (lo + hi + 1) // 2, внутри lo = mid и hi = mid - 1, ответ снова в lo. С обычной серединой он зацикливается на паре соседей — классическая ловушка. И ещё два места, где верная идея даёт неверное число: границы взяты узко, так что ответ вне отрезка, и предикат немонотонен — тогда приём неприменим вообще.

Приём 5. Числа поразрядно

XOR (^) складывает двоичные записи поразрядно и без переноса: $1 \oplus 1 = 0$, $1 \oplus 0 = 1$, $0 \oplus 0 = 0$. Например $22 \oplus 13$: записи $10110$ и $01101$ дают $11011 = 27$. Отсюда два равенства, на которых стоят все задачи про XOR: $x \oplus x = 0$ и $x \oplus 0 = x$; в цепочке всё, что встретилось дважды, гасится само.

Второй факт — про сравнение по разрядам. По пункту блока «Мост» один старший разряд больше суммы всех младших, поэтому варианты сравнивают начиная со старшего бита: выигрыш там перевешивает любой проигрыш во всех младших вместе взятых. На этом и стоит замена перебора пар спуском по дереву двоичных записей — то же деление пополам, что и в приёме 4, только режется множество кандидатов по очередному биту.

Отсюда правило для пар. Нужен максимальный XOR — на каждом разряде, начиная со старшего, ищи партнёра с противоположным битом (b1105); нужен минимальный — партнёра с таким же (s1101). У минимума есть ещё одно следствие того же факта: он всегда достигается на паре соседей в отсортированном порядке, то есть на маленьких данных хватает $n - 1$ проверки вместо всех пар.

Скрытые $O(n^{2})$ в Python

result += ch в цикле не дописывает символ, а копирует всю строку целиком: строки неизменяемы, и внешне линейный код оказывается квадратичным. Лечится накоплением в список и "".join(parts) в конце. Ловушка живучая: код проходит на маленьком тесте и упирается в предел на большом.

Что должно остаться в голове

  1. Ограничение в условии называет допустимую сложность; $10^{12}$ операций — это часы.
  2. list — порядок и индексы; set и dict — мгновенный поиск за счёт памяти; куча — $k$ крайних.
  3. «Было ли раньше» вместо «найдётся ли дальше»: множество для факта, счётчик для количества.
  4. Сумма отрезка — разность двух префиксов; «делится на $k$» — равенство остатков; c[0] = 1.
  5. Кадане — тот же вопрос к прошлым префиксам, только про минимум, а не про равенство.
  6. Окно линейно потому, что обе границы идут только вперёд; длина окна либо задана числом, либо задана условием.
  7. «Минимальное такое, что» плюс лёгкая проверка — бинарный поиск по ответу; шаблон hi = mid и lo = mid + 1, потом проверка соседа.
  8. $x \oplus x = 0$; старший разряд перевешивает все младшие вместе взятые: для максимума XOR партнёр с противоположным битом, для минимума — с таким же.
EN

Opening: two programs, both mathematically correct

An array contains a million numbers; how many pairs sum to 100? The naive approach uses two nested loops: roughly $5\cdot10^{11}$ pairs, so the program runs for hours. The smart approach makes one pass and asks the counter one question at every step: how many times has $100 - x$ already appeared? That is $10^{6}$ steps, or a fraction of a second. Both programs are mathematically correct, but only one will finish. The whole day is about recognizing within half a minute which of the two you have in mind, then writing it without edge-case mistakes.

Python for today

a = [3, 1, 4, 1, 5]
a[0], a[-1], a[1:4]                 # 3 5 [1, 4, 1] — zero-based; the right endpoint is excluded
sum(1 for v in a if v > 3)          # 2 — count by condition
sorted(a, reverse=True)[:3]         # [5, 4, 3]
7 // 2, 7 % 2, -(-7 // 2)           # 3 1 4 — floor division, remainder, CEILING
5 ^ 3, 5 >> 1, 5 & 1                # 6 2 1 — XOR, right shift, least significant bit
s = set(a); 3 in s                  # {1, 3, 4, 5}; True — only “present or absent”
from collections import Counter
c = Counter(a); c[1], c[42]         # 2 0 — a missing key returns zero, not an error
import heapq; heapq.nlargest(3, a)  # [5, 4, 3] without a full sort
for i, v in enumerate(a): pass      # index and value at once

Two lines here deserve special attention: -(-p // k) computes a ceiling without importing math (integer division rounds down), while Counter returns zero for a missing key, so the techniques below need no if key in d check.

How many operations can you afford?

Count operations rather than seconds: seconds depend on the machine, but the operation count depends only on the algorithm and input size $n$.

Complexity$n = 10^{3}$$n = 10^{5}$$n = 10^{6}$
$O(n)$$10^{3}$$10^{5}$$10^{6}$
$O(n\log n)$$10^{4}$$1.7\cdot10^{6}$$2\cdot10^{7}$
$O(n^{2})$$10^{6}$$10^{10}$$10^{12}$

A rule of thumb: a compiled language performs around $10^{8}$ simple operations per second; Python does an order of magnitude to an order and a half fewer. So $10^{10}$ operations take about two minutes even in a good case, while $10^{12}$ take roughly three hours.

The constraint in the statement is a complexity hint

$n \le 10^{3}$—a quadratic algorithm will pass. $n \le 10^{6}$—you need one pass, a sort, or a logarithm. $n \ge 10^{7}$—only one pass. Read the constraint before inventing a solution: it almost always names the technique.

StructureFastSlow or unavailableWhen to use it
listindexing, appendingvalue lookup—$O(n)$you need order and indices
setmembership check, insertion—$O(1)$no order or indicesyou only need presence/absence
dictkey lookup, insertion—$O(1)$no ordering by valueyou need to map a key to a number
heap (heapq)extract the minimum—$O(\log n)$arbitrary-element lookupyou need the $k$ extremes among $n$

Sets and dictionaries trade memory for speed, using several times more memory than a list. An interview-ready phrasing is: “Average $O(1)$ lookup, because the hash points straight to the right bucket; the cost is memory.”

Technique 1. Hash table: “seen before”

Two Sum. Does an array contain a pair whose sum is target? Naively, for each element you search to its right, which visits all pairs. The smart approach keeps a set seen of elements already passed and checks target - x in seen: one pass instead of two nested loops. The whole idea is to change the question from “will it appear later?” to “did it appear earlier?”

If the question asks how many such pairs there are, a set is not enough: it remembers a fact, not a count. You need a counter:

from collections import Counter
seen = Counter(); cnt = 0
for x in a:
    cnt += seen[target - x]     # how many matching values have appeared
    seen[x] += 1

“Find a pair” means a set; “count pairs” means a counter. Mixing up this fork silently undercounts the answer, and it is exactly what decides final y1101. The question asked of the counter changes from problem to problem: “how many times has $10 - x$ appeared” in b1101, “how many previous prefixes equal $S_r - 36$” in b1104, and “how many previous prefixes have the same remainder” in y1101. The question changes; the pass is the same.

Technique 2. Prefix sums

Define an accumulator $S_0 = 0$, $S_k = a_1 + \cdots + a_k$ in one loop, pre.append(pre[-1] + v). Then a segment sum is one difference, exactly as in Newton–Leibniz: the sum of elements with indices $l$ through $r$ inclusive is $S_{r+1} - S_l$. For $a = [4, 1, 6, 2, 5]$, we get $S = [0, 4, 5, 11, 13, 18]$, and the sum of indices 1 through 3 is $S_4 - S_1 = 13 - 4 = 9$, namely $1 + 6 + 2$.

Remainders are the key turn. How many subarrays have a sum divisible by $k$? A segment sum is $S_r - S_l$, and the “Bridge” fact says it is divisible by $k$ exactly when $S_r$ and $S_l$ have the same remainder. A question about segments becomes a question about pairs of prefixes with equal remainders—and the counter from technique 1 counts those pairs:

from collections import Counter
c = Counter({0: 1})        # the empty prefix participates too
s = 0; total = 0
for v in a:
    s = (s + v) % k
    total += c[s]          # all previous prefixes with the same remainder
    c[s] += 1

Check it by hand: $a = [3, 1, 4, 1, 5]$, $k = 3$. Prefixes are $[0, 3, 4, 8, 9, 14]$, with remainders $[0, 0, 1, 2, 0, 2]$. Remainder 0 appears three times, giving $\binom{3}{2} = 3$ pairs; remainder 2 appears twice, giving one more; remainder 1 gives none. The total is 4, and enumerating all fifteen subarrays gives the same result.

c[0] = 1 is not decoration

The empty prefix $S_0 = 0$ must be in the counter before the loop begins, or every subarray starting at the first element is lost. The code looks right, the answer is merely too small, and the cause is invisible without a walkthrough. This is topic mistake number one.

Kadane’s algorithm asks the same question of earlier prefixes. The maximum subarray sum ending at $r$ is $S_r - \min_{l < r} S_l$, so a running minimum is enough instead of pair enumeration. In the usual form it is two lines: cur = max(v, cur + v) and best = max(best, cur), initialized with best = cur = a[0]. Here cur is the best sum of a subarray ending at the current element, and the choice inside max decides whether to keep the left boundary or move it here. For the array $[5, -2, -6, 7, -1, 4]$, cur takes the values $5, 3, -3, 7, 6, 10$; the maximum 10 is the segment $[7, -1, 4]$, and enumerating all 21 subarrays agrees. Initializing best = 0 instead of a[0] is the main trap: on an all-negative array, that code returns zero.

Technique 3. Two pointers and the sliding window

Two-way movement. In a sorted array, find a pair with a given sum using pointers at the two ends: if the sum is too small, move the left pointer right; if it is too large, move the right pointer left. This is $O(n\log n)$ because of sorting—more expensive than a hash set, but it uses no extra hash-table memory.

Fixed-length window. The simplest case: the window length is given, both boundaries move together at every step, and the new sum is obtained from the old one in two operations—add the element arriving on the right and subtract the one leaving on the left (w1103). A full recomputation costs $O(nk)$; a shift costs $O(n)$ for any window length.

Variable-length window. Both pointers move in one direction: the right one expands the segment, and the left one catches up when the condition breaks. Find the longest subarray with sum at most 9 in $[6, 1, 2, 3, 1, 7, 2, 4]$:

a = [6, 1, 2, 3, 1, 7, 2, 4]
s = 0; left = 0; best = 0
for right, v in enumerate(a):
    s += v
    while s > 9:                # the condition broke—move the left boundary
        s -= a[left]; left += 1
    best = max(best, right - left + 1)
print(best)                     # 4

The answer is 4—the segment $[1, 2, 3, 1]$ has sum 7. Enumerating all 36 subarrays gives the same result, but the window makes one pass.

Why the window is linear

Each of the two pointers traverses the array exactly once and never moves backward, so there are at most $2n$ pointer moves, however many times the inner while runs. This is also the only thing you can break: if the left boundary jumps backward, correctness and linearity disappear together.

When the window condition is about composition rather than sum (“all characters are distinct”, “no more than two different letters”), keep the state in a dictionary: a character and its last index, or its occurrence count.

Technique 4. Binary search on the answer

In a sorted array, binary search finds an element in $\log_2 n$ steps. But the exam more often uses a different twist: search for the answer number itself, not for an array element. The signal is “the minimum such that” or “the maximum such that,” plus an easy check for a particular value. Example. Find the smallest integer $x$ with $x^{2} \ge 3000$. The predicate is x * x >= 3000, and it is monotone: if $x$ works, every larger value works too. The valid values form a ray, and we need its left boundary.

lo, hi = 1, 3000                # hi is guaranteed to work
while lo < hi:
    mid = (lo + hi) // 2
    if mid * mid >= 3000: hi = mid      # works—the boundary is no farther right than mid
    else:                 lo = mid + 1  # fails—mid is definitely too small
print(lo)                       # 55 in 12 steps instead of 3000 checks

Check the neighbor: $55^{2} = 3025 \ge 3000$, while $54^{2} = 2916 < 3000$—so 55 really is the boundary.

Memorize the template exactly

while lo < hi, with hi = mid and lo = mid + 1 inside; the answer is in lo. Invariant: hi always works and lo is the left edge of the search region; the interval strictly shrinks each step, so there is no infinite loop.

For “the maximum such that,” use the mirror template: mid = (lo + hi + 1) // 2, then lo = mid and hi = mid - 1; the answer is again in lo. With the ordinary midpoint it loops on two neighboring values—a classic trap. Two more places where a correct idea produces a wrong number: the bounds are too narrow, leaving the answer outside the interval, or the predicate is not monotone, in which case the technique does not apply at all.

Technique 5. Bitwise numbers

XOR (^) combines binary representations without carries: $1 \oplus 1 = 0$, $1 \oplus 0 = 1$, and $0 \oplus 0 = 0$. For example, $22 \oplus 13$: the representations $10110$ and $01101$ give $11011 = 27$. This yields the two identities behind every XOR problem: $x \oplus x = 0$ and $x \oplus 0 = x$; in a chain, anything that appears twice cancels itself.

The second fact concerns comparison by bits. The “Bridge” fact says that one higher bit is greater than the sum of all lower bits, so compare options starting with the most significant bit: a win there outweighs any loss across all lower bits together. This is what replaces pair enumeration with a descent through the binary-representation tree—the same halving idea as technique 4, except that candidates are split by the next bit.

That gives a rule for pairs. For the maximum XOR, at each bit from most significant to least, look for a partner with the opposite bit (b1105); for the minimum, look for one with the same bit (s1101). The minimum has another consequence of the same fact: it is always attained by a pair of neighbors in sorted order, so on small data it is enough to make $n - 1$ checks instead of checking every pair.

Hidden $O(n^{2})$ in Python

result += ch inside a loop does not append a character; it copies the entire string because strings are immutable, turning apparently linear code into quadratic code. Accumulate pieces in a list and use "".join(parts) at the end. This trap survives: the code passes small tests and hits the limit on large input.

What should stay in your head

  1. The constraint in the statement tells you the feasible complexity; $10^{12}$ operations take hours.
  2. list gives order and indices; set and dict give instant lookup at the cost of memory; a heap gives the $k$ extremes.
  3. Ask “was it seen earlier?” instead of “will it appear later?”: a set stores a fact, a counter stores a count.
  4. A segment sum is the difference of two prefixes; “divisible by $k$” means equal remainders; set c[0] = 1.
  5. Kadane’s algorithm asks the same question of earlier prefixes, but about a minimum rather than equality.
  6. A window is linear because both boundaries move only forward; its length is either fixed by a number or determined by a condition.
  7. “The minimum such that” plus an easy check means binary search on the answer; use hi = mid and lo = mid + 1, then check the neighbor.
  8. $x \oplus x = 0$; the highest bit outweighs all lower bits together: for maximum XOR use an opposite-bit partner, for minimum XOR use a same-bit partner.

Признаки и действия

Слева — что заметить в условии. Справа — что сделать первым.

УвиделПервый ход
Спрашивают про подотрезки и их суммыThey ask about subarrays and their sumsИспользуй префиксные суммы: сумма на отрезке равна разности двух значений накопителяUse prefix sums: a segment sum is the difference between two accumulator values
«Сумма делится на $k$»“The sum is divisible by $k$”Переходи к остаткам префиксов: одинаковый остаток означает, что разность кратна $k$; пары считай счётчиком и заранее положи в него пустой префиксSwitch to prefix remainders: equal remainders mean a difference divisible by $k$; count pairs and put the empty prefix into the counter first
«Самый длинный (или самый короткий) подотрезок, у которого …»“The longest (or shortest) subarray for which …”Окно: правый конец ведёт, левый догоняет, ответ обновляется на каждом шаге; левая граница никогда не идёт назадUse a window: the right end leads, the left catches up, and update the answer at every step; the left boundary never moves backward
«Минимальное такое, что» или «максимальное такое, что», и проверить значение легко“The minimum such that” or “the maximum such that,” with an easy value checkИспользуй бинарный поиск по ответу: сначала напиши предикат отдельной функцией, потом найди границу, потом проверь соседаUse binary search on the answer: first write the predicate as a separate function, then find the boundary, then check its neighbor
Пара элементов с заданной суммой, разностью или отношениемA pair of elements with a given sum, difference, or ratioОдин проход и словарь уже пройденного; «найти» — множество, «посчитать» — счётчикMake one pass with a dictionary of elements already seen; “find” means a set, “count” means a counter
Просят $k$ наибольших или $k$ наименьшихThey ask for the $k$ largest or $k$ smallestНе сортируй весь массив: heapq.nlargest или куча размера $k$ за $O(n\log k)$Do not sort the entire array: use heapq.nlargest or a heap of size $k$ in $O(n\log k)$
В условии ограничение $n \le 10^{5}$ и большеThe constraint says $n \le 10^{5}$ or largerКвадрат отпадает: ищи один проход, сортировку или логарифм, и скажи это вслух до того, как писать кодA quadratic solution is out: look for one pass, a sort, or a logarithm, and say so before writing code
Появились XOR, биты, двоичная записьXOR, bits, or binary representation appearРазбирай числа поразрядно, начиная со старшего бита: он перевешивает все младшие вместе взятые, поэтому для максимума XOR партнёр ищется с противоположным битом, для минимума — с таким же, а на маленьких данных минимальный XOR достаточно поискать среди соседей отсортированного спискаProcess numbers bit by bit from the most significant bit: it outweighs all lower bits together, so maximum XOR looks for an opposite-bit partner, minimum XOR for a same-bit partner; on small data, find the minimum XOR among adjacent values in sorted order
эталонная задача

Минимальная грузоподъёмность: как довести «минимальное такое, что» до числаMinimum capacity: turning “the minimum such that” into a number

RU

Условие. Восемь посылок весами $[7, 2, 5, 10, 8, 3, 6, 4]$ стоят в очереди, и порядок менять нельзя. Каждый день грузовик увозит несколько первых оставшихся посылок подряд, суммарный вес которых не превосходит его грузоподъёмности $C$. Все посылки надо увезти за 4 дня. Найти минимальное целое $C$.

Важны не числа, а порядок ходов: та же последовательность закрывает мост b1107 и финал y1102 — единственную задачу ступени YMLS с признаком из шага 1.

Шаг 1. Решить, что именно ищем. В условии сказано «минимальное $C$, при котором всё увезут за 4 дня». Искомое — не элемент какого-то массива, а число с параметром. Это и есть признак бинарного поиска по ответу; дальше массив посылок нас интересует только как способ проверить одно конкретное $C$.

Шаг 2. Написать предикат, а не решение. Отдельной функцией — «уложимся ли за 4 дня при грузоподъёмности $C$». Раскладка по дням тут жадная и других вариантов не имеет: класть в текущий день, пока влезает, иначе начинать новый день.

w = [7, 2, 5, 10, 8, 3, 6, 4]

def days(cap):
    d, cur = 1, 0
    for x in w:
        if cur + x <= cap:
            cur += x
        else:
            d += 1; cur = x
    return d

Шаг 3. Проверить монотонность. Чем больше грузоподъёмность, тем не больше дней: всё, что помещалось при $C$, помещается и при $C + 1$. Значит годные значения образуют луч, и у него есть левая граница. Без этой проверки бинарный поиск применять нельзя — на немонотонном предикате он найдёт случайное число.

Шаг 4. Назначить границы так, чтобы ответ заведомо попал внутрь. Слева $\text{lo} = \max w = 10$: при меньшей грузоподъёмности самая тяжёлая посылка не уедет никогда. Справа $\text{hi} = \sum w = 45$: этого хватит на один день. Отрезок $[10, 45]$ содержит ответ, и hi заведомо годится — то, что требует инвариант шаблона.

Шаг 5. Прокрутить шаблон. Пять шагов, и отрезок из 36 кандидатов схлопывается:

lohimiddays(mid)годитсячто делаем
1045272даhi = 27
1027183даhi = 18
1018144даhi = 14
1014125нетlo = 13
1314135нетlo = 14

Границы сошлись: $\text{lo} = \text{hi} = 14$.

Шаг 6. Проверить соседа — обязательный шаг, а не украшение. При $C = 14$ дни складываются в $[7, 2, 5]$, $[10]$, $[8, 3]$, $[6, 4]$ — ровно 4 дня. При $C = 13$ первый день берёт только $[7, 2]$, и всего дней получается 5. Значит 14 — граница, и ответ 14.

Алгоритм
  1. Увидел «минимальное (максимальное) такое, что» — ищи не элемент, а само число ответа.
  2. Напиши предикат ok(t) отдельной функцией и проверь его на двух-трёх значениях руками.
  3. Убедись, что предикат монотонен: иначе бинарный поиск неприменим.
  4. Возьми lo и hi с запасом, чтобы ответ лежал внутри, а hi заведомо годился.
  5. Крути шаблон hi = mid / lo = mid + 1, а в конце проверь соседа lo - 1.
EN

Problem. Eight parcels with weights $[7, 2, 5, 10, 8, 3, 6, 4]$ stand in a queue, and their order cannot be changed. Each day, a truck takes several consecutive parcels from the front of the remaining queue, with total weight no greater than its capacity $C$. All parcels must be transported in 4 days. Find the minimum integer $C$.

The numbers are not the point; the sequence of moves is. The same sequence solves bridge b1107 and final y1102—the only YMLS-level problem signaled by step 1.

Step 1. Decide what you are searching for. The statement says “the minimum $C$ that gets everything away in 4 days.” The target is not an element of an array but a parameterized number. That is the signal for binary search on the answer; the parcel array matters only as a way to check one particular $C$.

Step 2. Write a predicate, not a solution. Put “can we finish in 4 days with capacity $C$?” in a separate function. The day-by-day packing is greedy and has no alternatives: keep adding to the current day while the next parcel fits; otherwise start a new day.

w = [7, 2, 5, 10, 8, 3, 6, 4]

def days(cap):
    d, cur = 1, 0
    for x in w:
        if cur + x <= cap:
            cur += x
        else:
            d += 1; cur = x
    return d

Step 3. Check monotonicity. The larger the capacity, the no more days are needed: everything that fit with $C$ also fits with $C + 1$. So the valid values form a ray with a left boundary. Without this check, binary search is not allowed—on a non-monotone predicate it returns an arbitrary number.

Step 4. Choose bounds that definitely contain the answer. On the left, take $\text{lo} = \max w = 10$: with less capacity, the heaviest parcel can never be transported. On the right, take $\text{hi} = \sum w = 45$: that is enough for one day. The interval $[10, 45]$ contains the answer, and hi is guaranteed to work, as required by the template invariant.

Step 5. Run the template. Five steps collapse the interval of 36 candidates:

lohimiddays(mid)worksaction
1045272yeshi = 27
1027183yeshi = 18
1018144yeshi = 14
1014125nolo = 13
1314135nolo = 14

The bounds meet: $\text{lo} = \text{hi} = 14$.

Step 6. Check the neighbor—mandatory, not decorative. With $C = 14$, the days are $[7, 2, 5]$, $[10]$, $[8, 3]$, $[6, 4]$—exactly 4 days. With $C = 13$, the first day can take only $[7, 2]$, which makes 5 days in total. So 14 is the boundary and the answer is 14.

Algorithm
  1. See “the minimum (maximum) such that”? Search for the answer number, not an array element.
  2. Write ok(t) as a separate function and test it by hand on two or three values.
  3. Confirm that the predicate is monotone; otherwise binary search does not apply.
  4. Choose lo and hi with enough slack that the answer is inside and hi definitely works.
  5. Run hi = mid / lo = mid + 1, then check the neighbor lo - 1 at the end.

Дополнительные материалы

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

интерактивVisuAlgo · визуализация алгоритмовVisuAlgo · algorithm visualizations EN
Бинарный поиск, сортировки и структуры данных в анимации, шаг за шагом. Лучший способ увидеть, что происходит внутриBinary search, sorting, and data structures in animation, step by step. The best way to see what happens inside
интерактивPython Tutor · пошаговое исполнение кодаPython Tutor · step-by-step code execution EN
Вставляешь код и смотришь, как меняются переменные на каждой строке. Незаменимо, когда не понимаешь, почему программа делает не тоPaste in code and watch variables change on every line. Indispensable when you cannot see why a program behaves incorrectly
видеоErrichto · Binary Search tutorialErrichto · Binary Search tutorial EN
Четвёртый приём дня — бинарный поиск по ответу — разобран отдельно: как написать предикат, где ставить границы и почему цикл не зацикливается. С кодом на PythonToday’s fourth technique—binary search on the answer—explained separately: how to write the predicate, choose bounds, and avoid an infinite loop. Includes Python code
текстBig-O Cheat SheetBig-O Cheat Sheet EN
Одна таблица: сложность каждой операции для списка, множества, словаря и кучи плюс все сортировки. Держать открытой, пока приём не доведён до числаOne table with the complexity of every list, set, dictionary, and heap operation, plus all sorting algorithms. Keep it open until the technique is carried through to a number
текстNeetcode · разбор шаблоновNeetcode · pattern walkthroughs EN
Задачи, сгруппированные по приёмам, а не по темам. Именно то, что нужно при подготовке за короткий срокProblems grouped by technique rather than topic. Exactly what you need when preparing in a short time
как работать сегодня
RU

Задачи дня выстроены в лестницу из четырёх ступеней, и идти по ним надо по порядку: каждая следующая ступень пользуется тем, что отработано на предыдущей.

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

Полный объём — 16 задач. Всё, что есть на странице, включая ступень ШАД. Это план на день, который идёт хорошо.

Минимум — 10 задач. b1101, b1102, b1103, b1104, b1106, b1107, y1101, y1102, y1103, y1104 — четыре моста ступени 3, две базовые техники ступени 2 и все четыре финала уровня YMLS. Разминка w1101–w1104 в этот счёт не входит, но не выбрасывается: она делается сразу после урока, по минуте на задачу, и каждая из четырёх — простейшая версия одного из приёмов: множество, XOR, окно постоянной длины, деление отрезка пополам.

Обязательные — 4 задачи. b1102, b1104, b1106, b1107 — четыре моста ступени 3 из пяти. b1102 ведёт к y1104: та же куча размера пять, только в финале спрашивают не её вершину, а сумму содержимого. b1104 ведёт к y1101: там счётчик спрашивают про равные суммы, в финале — про равные остатки, всё остальное совпадает дословно. b1106 ведёт к мини-тесту y1103: то же окно по строке, только условие на состав другое. b1107 ведёт к y1102: тот же бинарный поиск по ответу, только зеркальный — максимум вместо минимума и целая часть вместо округления вверх. Если день сорвался и осталось сорок минут — делаются эти четыре и мини-тест.

Пятый мост ступени 3 — b1105. Он ведёт к задаче ШАД s1101. Этот мост не входит в минимум по той же причине, что и сама задача.

Дриль на скорость. Задачу b1101 реши тремя способами: наивным перебором пар, двумя указателями на отсортированной копии и счётчиком за один проход. Для каждого произнеси вслух сложность по времени и по памяти. Это ровно то, чего ждут на собеседовании: не «работает», а «работает за столько-то».

Бинарный поиск напиши с нуля, не пользуясь модулем bisect, и проверь на краевых случаях: искомое в самом начале, в самом конце, отсутствует вовсе. Потом отдельно — бинарный поиск по ответу по шаблону из эталонной задачи.

Кадане — без задачи в банке, но с проверкой. Отдельной задачи на максимальную сумму подотрезка сегодня нет, приём разобран в приёме 2 урока. Напиши его сам на массиве $[5, -2, -6, 7, -1, 4]$, получи 10 и сверь с перебором всех 21 подотрезка. Двух минут хватает, а ловушка с начальным best = 0 вместо a[0] ловится только так.

Про мост b1105 и задачу ШАД s1101

Обе на своих данных решаются перебором пар — двадцати восьми и сорока пяти, — то есть уже освоенными средствами: XOR из w1102 плюс перебор пар из b1101. Ценность их не в ответе, а в идее «старший разряд перевешивает все младшие», которая превращает перебор в спуск по разрядам: в b1105 — к максимуму, в s1101 — к минимуму. В минимальный объём эта пара не входит; если времени нет, переносится именно она, а не остальные мосты.

Что говорить на собеседовании
  1. Уточнить краевые случаи до написания кода.
  2. Назвать наивное решение и его сложность вслух.
  3. Предложить улучшение и объяснить, за счёт чего оно работает.
  4. Написать код, проговаривая шаги. Не молчать дольше 15 секунд.
  5. Назвать итоговую сложность по времени и по памяти.

Молчащий кандидат теряет баллы, даже если решает верно.

EN

Today’s problems form a four-level ladder, and you should climb it in order: each level builds on what the previous one rehearsed.

Write and run every problem as code. Not in your head and not on paper: in the exam you will type, and muscle memory matters more here than understanding. Today’s rule: before running, say the technique and complexity aloud; after running, compare the answer with an order-of-magnitude estimate.

Full volume: 16 problems. Everything on the page, including the SHAD level. This is the plan for a day that goes well.

Minimum: 10 problems. b1101, b1102, b1103, b1104, b1106, b1107, y1101, y1102, y1103, y1104—the four level-3 bridges, two level-2 fundamentals, and all four YMLS-level finals. The warm-up w1101–w1104 does not count toward this total, but do not discard it: do it immediately after the lesson, one minute per problem. Each is the simplest version of a technique: a set, XOR, a fixed-length window, and halving an interval.

Mandatory: 4 problems. b1102, b1104, b1106, b1107—four of the five level-3 bridges. b1102 leads to y1104: the same heap of size five, except the final asks for the sum of its contents rather than its top. b1104 leads to y1101: the counter is asked about equal sums there and equal remainders in the final; everything else is word-for-word the same. b1106 leads to mini-test y1103: the same string window, with a different composition condition. b1107 leads to y1102: the same binary search on the answer, mirrored— maximum instead of minimum, and floor instead of ceiling. If the day goes wrong and only forty minutes remain, do these four and the mini-test.

The fifth level-3 bridge is b1105. It leads to SHAD problem s1101. This bridge is excluded from the minimum for the same reason as the problem itself.

Speed drill. Solve b1101 three ways: naive pair enumeration, two pointers on a sorted copy, and a one-pass counter. For each, say the time and space complexity aloud. That is exactly what interviews expect: not “it works,” but “it works in this much time.”

Write binary search from scratch, without bisect, and test edge cases: the target at the very beginning, at the very end, and absent. Then separately write binary search on the answer using the template from the reference problem.

Kadane’s algorithm—no bank problem, but verify it. There is no separate maximum-subarray-sum problem today; the technique is explained in lesson technique 2. Write it yourself for $[5, -2, -6, 7, -1, 4]$, get 10, and compare it with enumerating all 21 subarrays. Two minutes are enough, and the trap of initializing best = 0 instead of a[0] is caught only this way.

About bridge b1105 and SHAD problem s1101

On their own data, both can be solved by enumerating pairs—28 and 45 of them—using techniques already learned: XOR from w1102 plus pair enumeration from b1101. Their value is not the answer but the idea that “the highest bit outweighs all lower bits,” which turns enumeration into a descent through the bits: toward the maximum in b1105, toward the minimum in s1101. This pair is not part of the minimum volume; if time runs out, defer these two, not the other bridges.

What to say in an interview
  1. Clarify edge cases before writing code.
  2. Say the naive solution and its complexity out loud.
  3. Propose an improvement and explain what makes it work.
  4. Write the code while narrating the steps. Do not stay silent for more than 15 seconds.
  5. State the final time and space complexity.

A silent candidate loses points even with a correct solution.

16
полный объём
10
минимум
4
обязательные

Полный объём — все задачи ниже. Минимум — если день сорвался и часа осталось два. Обязательные — мосты к финальной задаче, они не пропускаются никогда.

Разминка

решено 4 из 4

Устно, за полминуты. Проверяет, что определение понято, а не выучено.

W1101Разминкаступень 1Алгоритмы✓разминка
RU

Дан массив из тридцати чисел:

a = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7]

Сколько в нём различных значений?

EN

Consider the following array of thirty numbers:

a = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7]

How many distinct values does it contain?

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$), во второй — $n$ целых чисел $a_i$ ($|a_i| \le 10^9$). Вывод. Одно число — количество различных значений.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$); the second holds $n$ integers $a_i$ ($|a_i| \le 10^9$). Output. One number: how many distinct values there are.

ВыводOutput
Подсказка / Hint
RU

Структура, которая по определению не хранит повторов.

EN

Use the data structure that, by definition, stores no duplicates.

Решение / Solution
RU
print(len(set(a)))   # 9

Ответ: 9. Множество убирает дубликаты само — это его определяющее свойство, и стоит построение $O(n)$: каждый элемент кладётся один раз, а проверка «уже есть?» внутри множества мгновенная.

Куда это ведёт

Тот же set за ту же цену отвечает на вопрос «встречалось ли значение», и на этом стоит весь приём «видел раньше»: b1101, а через счётчик — мост b1104 и финал y1101. Ровно этот массив используется в w1103, b1101–b1104, y1101 и y1104; остальные задачи дня работают на своих данных.

EN
print(len(set(a)))   # 9

Answer: 9. A set removes duplicates automatically; this is its defining property. Building it takes $O(n)$ time: each element is inserted once, and membership testing is constant time on average.

Where this leads

The same set, at the same cost, answers “has this value occurred before?” This is the basis of the entire “seen before” technique in b1101, and via a frequency counter it leads to b1104 and the final problem y1101. This exact array is used in w1103, b1101–b1104, y1101, and y1104; the remaining problems of the day use their own data.

уверенность1 — угадал, 5 — уверен полностью
W1102Разминкаступень 1Алгоритмы✓разминка
RU

Вычислите побитовое исключающее ИЛИ (XOR) всех элементов массива

[11, 4, 7, 4, 20, 11, 7, 20, 13]

то есть значение $11 \oplus 4 \oplus 7 \oplus 4 \oplus 20 \oplus 11 \oplus 7 \oplus 20 \oplus 13$.

EN

Calculate the bitwise exclusive OR (XOR) of all elements of the array

[11, 4, 7, 4, 20, 11, 7, 20, 13]

that is, calculate $11 \oplus 4 \oplus 7 \oplus 4 \oplus 20 \oplus 11 \oplus 7 \oplus 20 \oplus 13$.

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$), во второй — $n$ целых чисел $0 \le a_i < 2^{30}$. Вывод. XOR всех элементов.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$); the second holds $n$ integers $0 \le a_i < 2^{30}$. Output. The XOR of all elements.

ВыводOutput
Подсказка / Hint
RU

XOR не зависит от порядка слагаемых. Посмотри, какие значения в списке повторяются.

EN

XOR is independent of the order of the operands. Look for values that occur more than once.

Решение / Solution
RU

XOR складывает двоичные записи поразрядно и без переноса. Для одной пары это выглядит так: $11 = 1011_2$, $4 = 0100_2$, поэтому $11 \oplus 4 = 1111_2 = 15$.

Считать все восемь операций подряд не нужно. XOR не зависит от порядка, а $x \oplus x = 0$ и $x \oplus 0 = x$, поэтому каждая пара одинаковых значений гасится: числа 11, 4, 7 и 20 встречаются дважды и исчезают.

$$11 \oplus 4 \oplus 7 \oplus 4 \oplus 20 \oplus 11 \oplus 7 \oplus 20 \oplus 13 = 13$$
x = 0
for v in [11, 4, 7, 4, 20, 11, 7, 20, 13]:
    x ^= v
print(x)     # 13

Ответ: 13.

Куда это ведёт

Это стандартный приём «найти непарный элемент за один проход и без дополнительной памяти»: если каждое значение встречается дважды, кроме одного, XOR всего массива и есть это одно. Дальше тема идёт мостом b1105 (наибольший XOR пары) и финалом s1101 (наименьший): там работает её вторая половина — сравнение чисел по разрядам, начиная со старшего.

EN

XOR combines binary representations bit by bit without carrying. For one pair, $11 = 1011_2$ and $4 = 0100_2$, so $11 \oplus 4 = 1111_2 = 15$.

There is no need to perform all eight operations in sequence. XOR is commutative and associative, and $x \oplus x = 0$, $x \oplus 0 = x$. Thus every equal pair cancels: 11, 4, 7, and 20 each occur twice and disappear.

$$11 \oplus 4 \oplus 7 \oplus 4 \oplus 20 \oplus 11 \oplus 7 \oplus 20 \oplus 13 = 13$$
x = 0
for v in [11, 4, 7, 4, 20, 11, 7, 20, 13]:
    x ^= v
print(x)     # 13

Answer: 13.

Where this leads

This is the standard technique for finding the unpaired element in one pass and with constant extra memory: if every value occurs twice except one, the XOR of the entire array is that one value. The topic continues through bridge problem b1105 (maximum XOR of a pair) and final problem s1101 (minimum XOR). Those problems use the other half of the idea: comparing numbers bit by bit, starting with the most significant bit.

уверенность1 — угадал, 5 — уверен полностью
W1103Разминкаступень 1Алгоритмы✓разминка
RU

По массиву из задачи w1101 едет окно длины 5 — пять подряд идущих элементов. Первое окно стоит на позициях с нулевой по четвёртую, его сумма равна $3+1+4+1+5 = 14$; дальше окно каждый раз сдвигается на одну позицию вправо, пока правый конец не упрётся в последний элемент. Всего положений $30 - 5 + 1 = 26$.

Найдите наибольшую сумму окна.

EN

A window of length 5 moves along the array from problem w1101; each window consists of five consecutive elements. The first window occupies positions zero through four and has sum $3+1+4+1+5 = 14$. The window then moves one position to the right at a time until its right endpoint reaches the last element. There are $30 - 5 + 1 = 26$ positions in total.

Find the largest window sum.

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ и $k$ ($1 \le k \le n \le 10^5$), во второй — $n$ целых чисел ($|a_i| \le 10^4$, бывают отрицательные). Вывод. Наибольшая сумма $k$ подряд идущих элементов.

EN

Input. The first line holds $n$ and $k$ ($1 \le k \le n \le 10^5$); the second holds $n$ integers ($|a_i| \le 10^4$, negatives allowed). Output. The largest sum of $k$ consecutive elements.

ВыводOutput
Подсказка / Hint
RU

Соседнее окно отличается от текущего двумя элементами: один ушёл слева, один пришёл справа. Значит новая сумма получается из старой за два действия, а не пересчётом всех пяти слагаемых.

EN

Two adjacent windows differ in exactly two elements: one leaves on the left and one enters on the right. Thus the new sum requires two updates, not a fresh sum of all five elements.

Решение / Solution
RU
s = sum(a[:5]); best = s
for right in range(5, len(a)):
    s += a[right] - a[right - 5]     # пришёл правый, ушёл левый
    best = max(best, s)
print(best)                          # 38

Ответ: 38 — окно [5, 8, 9, 7, 9], элементы с десятого по четырнадцатый.

Полный пересчёт каждого окна стоил бы $O(nk)$ действий, сдвиг стоит $O(n)$ независимо от длины окна: каждый элемент ровно один раз прибавляется, когда в окно входит, и ровно один раз вычитается, когда из него выходит.

Куда это ведёт

Это окно самое простое: длина у него постоянна, поэтому левый конец сдвигается на каждом шаге вместе с правым. В мосте b1106 и в мини-тесте y1103 длину окна задаёт не число, а условие («не больше двух разных букв», «все символы различны»), и левый конец догоняет правый рывками, внутри while. Общее у всех трёх — обе границы идут только вперёд, и потому проход остаётся один.

EN
s = sum(a[:5]); best = s
for right in range(5, len(a)):
    s += a[right] - a[right - 5]     # add the right item, remove the left
    best = max(best, s)
print(best)                          # 38

Answer: 38, attained by the window [5, 8, 9, 7, 9], elements ten through fourteen.

Recomputing every window from scratch would take $O(nk)$ operations. Sliding the window takes $O(n)$ time regardless of its length: each element is added exactly once when it enters and subtracted exactly once when it leaves.

Where this leads

This is the simplest kind of window: its length is fixed, so its left endpoint moves on every step together with the right endpoint. In b1106 and the mini-test y1103, the window length is determined by a condition (“at most two distinct letters,” “all characters are distinct”), so the left endpoint catches up with the right one in jumps inside a while loop. In all three problems, both endpoints move only forward, which keeps the algorithm linear.

уверенность1 — угадал, 5 — уверен полностью
W1104Разминкаступень 1Алгоритмы✓разминка
RU

Шаблон бинарного поиска из урока сужает отрезок кандидатов так, что после каждого шага их остаётся не больше половины прежнего:

while lo < hi:
    mid = (lo + hi) // 2
    if ok(mid): hi = mid
    else:       lo = mid + 1

Сколько раз выполнится тело этого цикла, если кандидатов ровно 1024?

EN

The binary-search template from the lesson narrows the interval of candidates so that at most half of the previous candidates remain after every iteration:

while lo < hi:
    mid = (lo + hi) // 2
    if ok(mid): hi = mid
    else:       lo = mid + 1

How many times is the loop body executed if there are exactly 1024 candidates?

верно
Python · решить кодомsolve in code
RU

Здесь нет тестов: программа должна напечатать ответ последней строкой. «Сдать вывод как ответ» подставит его в поле ответа и проверит как обычно.

EN

This problem has no tests: the program must print the answer on its last line. “Submit output” puts it into the answer box and checks it as usual.

ВыводOutput
Подсказка / Hint
RU

Считай, сколько раз число 1024 делится пополам, пока не останется единица.

EN

Count how many times 1024 can be halved before only one candidate remains.

Решение / Solution
RU

Каждый шаг оставляет не больше половины кандидатов:

$$1024 \to 512 \to 256 \to 128 \to 64 \to 32 \to 16 \to 8 \to 4 \to 2 \to 1$$

Это $\log_2 1024 = 10$ делений, и цикл заканчивается, когда кандидат остался один.

Ответ: 10.

Число шагов у этого шаблона не зависит от того, где именно лежит ответ: цикл всегда доводит отрезок до одного элемента. Для сравнения, перебор кандидатов подряд в худшем случае сделает 1024 шага, а для миллиона кандидатов бинарный поиск обойдётся двадцатью шагами вместо миллиона.

Куда это ведёт

Здесь и лежит причина, по которой бинарный поиск по ответу дёшев даже тогда, когда проверка одного значения не бесплатна: предикат вызывается два десятка раз, а не миллион. В b1107 и в финале y1102 каждый вызов предиката — это целый проход по данным, и всё равно решение мгновенное.

EN

Each iteration leaves at most half of the candidates:

$$1024 \to 512 \to 256 \to 128 \to 64 \to 32 \to 16 \to 8 \to 4 \to 2 \to 1$$

This takes $\log_2 1024 = 10$ halvings, and the loop terminates when one candidate remains.

Answer: 10.

The number of iterations of this template does not depend on where the answer lies: the loop always reduces the interval to one element. By comparison, a linear scan may need 1024 steps in the worst case; with one million candidates, binary search needs about twenty steps rather than one million.

Where this leads

This explains why binary search on the answer is inexpensive even when checking one candidate is not free: the predicate is called about twenty times rather than one million. In b1107 and the final problem y1102, every predicate call makes a complete pass over the data, yet the solution is still fast.

уверенность1 — угадал, 5 — уверен полностью

База

решено 3 из 7

Чистая техника без сюрпризов. Здесь нарабатывается автоматизм.

B1101Базаступень 2минимумАлгоритмы✓авторская · шаблон Two Sum
RU

Для массива из задачи w1101 найдите, сколько существует пар индексов $i < j$, для которых $a_i + a_j = 10$. Пары, различающиеся индексами, считаются разными, даже если значения в них одинаковые.

EN

For the array from problem w1101, find the number of pairs of indices $i < j$ such that $a_i + a_j = 10$. Pairs with different indices are considered distinct even if their values coincide.

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$) и $T$, во второй — $n$ целых чисел. Вывод. Количество пар индексов $i < j$ с $a_i + a_j = T$.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$) and $T$; the second holds $n$ integers. Output. The number of index pairs $i < j$ with $a_i + a_j = T$.

ВыводOutput
Подсказка / Hint
RU

Наивно — два вложенных цикла за $O(n^2)$. За $O(n)$ — счётчик уже встреченных значений.

EN

The naive solution uses two nested loops and takes $O(n^2)$ time. An $O(n)$ solution uses a frequency counter of values seen so far.

Решение / Solution
RU

Решение за $O(n)$. Идём слева направо и для каждого элемента $x$ задаём счётчику один вопрос: сколько раз уже встречалось $10 - x$? Каждая такая встреча — готовая пара, у которой левый индекс меньше правого.

from collections import Counter
seen = Counter(); cnt = 0
for x in a:
    cnt += seen[10 - x]     # все подходящие, встреченные ранее
    seen[x] += 1
print(cnt)                  # 44

Ответ: 44.

Почему счётчик, а не множество

В массиве есть повторяющиеся значения. Множество ответило бы только «встречалось или нет», а нам нужно сколько раз. С множеством ответ получился бы заниженным.

Это типичная развилка: «найти пару» — множество, «посчитать пары» — счётчик. В финале y1101 спрашивают именно количество, поэтому там тоже стоит Counter.

Дриль дня

Эту задачу надо решить тремя способами: наивным перебором пар за $O(n^2)$, двумя указателями по отсортированной копии за $O(n\log n)$ и счётчиком за $O(n)$. Все три обязаны дать 44. Для каждого произнеси вслух сложность по времени и по памяти — это стандартный вопрос собеседования, и спрашивают его именно так.

EN

An $O(n)$ solution. Scan from left to right. For each element $x$, ask the counter how many times $10-x$ has already occurred. Each such occurrence forms a valid pair whose left index is smaller.

from collections import Counter
seen = Counter(); cnt = 0
for x in a:
    cnt += seen[10 - x]     # all matching values seen earlier
    seen[x] += 1
print(cnt)                  # 44

Answer: 44.

Why a counter rather than a set?

The array contains repeated values. A set would answer only “has this occurred?” whereas we need to know how many times it has occurred, so using a set would undercount.

This is a common fork: use a set to “find a pair,” but a counter to “count the pairs.” Final problem y1101 also asks for a count and therefore uses Counter.

Practice drill

Solve this problem in three ways: a naive pair enumeration in $O(n^2)$ time, two pointers on a sorted copy in $O(n\log n)$ time, and a counter in $O(n)$ time. All three must give 44. For each method, state its time and space complexity aloud. This is a standard interview question, asked in exactly this form.

уверенность1 — угадал, 5 — уверен полностью
B1102Базаступень 3обязательнаяАлгоритмы✓авторская · мост к y1104
RU

Для массива из задачи w1101 найдите пятый по величине элемент: тот, который окажется пятым, если выписать все тридцать элементов по невозрастанию. Одинаковые значения при этом не склеиваются — каждое повторение занимает своё отдельное место.

Полной сортировкой пользоваться нельзя. Пройдите по массиву, держа кучу-минимум из пяти лучших элементов: как только в куче оказывается шестой, наименьший выбрасывается. Ответ — то, что останется на вершине кучи в конце прохода.

В настоящей постановке этой задачи $n \le 10^{6}$ при $k = 5$; здесь $n = 30$, чтобы ответ можно было проверить руками.

EN

For the array from problem w1101, find the fifth-largest element, meaning the element that appears fifth when all thirty elements are listed in nonincreasing order. Equal values are not merged; every occurrence occupies a separate position.

You may not sort the entire array. Make one pass while maintaining a min-heap containing the five largest elements seen so far. Whenever a sixth element enters the heap, remove its smallest element. The answer is the element at the top of the heap after the pass.

In the full version of this problem, $n \le 10^{6}$ and $k = 5$. Here $n = 30$, so the answer can be checked by hand.

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ и $k$ ($1 \le k \le n \le 10^5$), во второй — $n$ целых чисел. Вывод. $k$-й по величине элемент: повторы занимают отдельные места.

EN

Input. The first line holds $n$ and $k$ ($1 \le k \le n \le 10^5$); the second holds $n$ integers. Output. The $k$-th largest element, with repeats taking separate places.

ВыводOutput
Подсказка / Hint
RU

Куча размера $k$ хранит $k$ лучших из уже просмотренных, а на вершине держит худший из этих $k$. Вершина и есть $k$-й по величине элемент.

EN

A heap of size $k$ stores the $k$ best elements seen so far, with the worst among them at the top. That top element is the $k$-th largest.

Решение / Solution
RU
import heapq
h = []
for v in a:
    heapq.heappush(h, v)
    if len(h) > 5:
        heapq.heappop(h)     # выбрасываем наименьший из шести
print(h[0])                  # 8 — вершина кучи и есть пятый по величине

Ответ: 8. По невозрастанию массив начинается так: $9, 9, 9, 8, 8, 8, 7, \ldots$ — девятка встречается трижды, поэтому четвёртое, пятое и шестое места занимают восьмёрки.

Элементы, а не различные значения

Пятое по величине различное значение — это 5: различные значения по убыванию идут $9, 8, 7, 6, 5$. Прочитанное так условие даёт 5 вместо 8, и вся разница — в одном слове. Ту же развилку проверяют в финале y1104.

Почему куча, а не сортировка

Куча размера $k$ стоит $O(n\log k)$: каждый элемент один раз кладётся и не больше одного раза вынимается, а внутри кучи всё время пять элементов. Полная сортировка стоит $O(n\log n)$. При $n = 10^{6}$ и $k = 5$ это разница между $2.3\cdot10^{6}$ и $2\cdot10^{7}$ сравнений — тот случай, когда ограничение из условия прямо называет структуру данных, и назвать её надо до того, как писать код.

Финал y1104 — этот же проход, только вопрос в конце другой: не вершина кучи, а сумма всех пяти её элементов. Готовая обёртка heapq.nlargest(k, a) делает ровно описанное здесь.

EN
import heapq
h = []
for v in a:
    heapq.heappush(h, v)
    if len(h) > 5:
        heapq.heappop(h)     # discard the smallest of the six
print(h[0])                  # 8 — the heap root is the fifth largest

Answer: 8. In nonincreasing order, the array begins $9, 9, 9, 8, 8, 8, 7, \ldots$. The value 9 occurs three times, so positions four, five, and six are occupied by 8s.

Elements, not distinct values

The fifth-largest distinct value would be 5, since the distinct values in decreasing order are $9, 8, 7, 6, 5$. Reading the statement this way produces 5 instead of 8; the entire distinction lies in one word. Final problem y1104 tests the same distinction.

Why use a heap rather than sorting?

A heap of size $k$ gives $O(n\log k)$ time: every element is inserted once and removed at most once, while the heap always contains only five elements. Full sorting costs $O(n\log n)$. For $n = 10^{6}$ and $k = 5$, this is the difference between $2.3\cdot10^{6}$ and $2\cdot10^{7}$ comparisons. The input constraint directly identifies the appropriate data structure, and you should identify it before writing code.

Final problem y1104 uses the same pass but asks a different final question: it needs the sum of all five heap elements rather than the top. The convenience function heapq.nlargest(k, a) performs exactly the procedure described here.

уверенность1 — угадал, 5 — уверен полностью
B1103Базаступень 2минимумАлгоритмы✓авторская · префиксные суммы
RU

Для массива из задачи w1101 постройте префиксные суммы $S_0 = 0$, $S_k = a_1 + \cdots + a_k$. Сколько среди тридцати одного числа $S_0, S_1, \ldots, S_{30}$ различных значений?

EN

For the array from problem w1101, construct the prefix sums $S_0 = 0$ and $S_k = a_1 + \cdots + a_k$. How many distinct values occur among the thirty-one numbers $S_0, S_1, \ldots, S_{30}$?

верно
Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$), во второй — $n$ целых чисел (бывают нули и отрицательные). Вывод. Сколько различных значений среди $S_0 = 0, S_1, \ldots, S_n$.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$); the second holds $n$ integers (zeros and negatives allowed). Output. How many distinct values there are among $S_0 = 0, S_1, \ldots, S_n$.

ВыводOutput
Подсказка / Hint
RU

Посмотри на знаки элементов массива, прежде чем что-то считать.

EN

Inspect the signs of the array elements before calculating anything.

Решение / Solution
RU
pre = [0]
for v in a:
    pre.append(pre[-1] + v)
print(len(set(pre)))    # 31

Ответ: 31.

Это можно было понять без кода

Все элементы массива строго положительны, значит последовательность префиксных сумм строго возрастает, значит все 31 значение различны — и считать нечего.

Навык «посмотреть на структуру данных вместо того, чтобы считать» экономит на экзамене больше времени, чем любая оптимизация кода.

Куда это ведёт

Строгий рост префиксов означает, что в мосте b1104 каждое значение суммы встретится не больше одного раза. А в финале y1101 вместо самих сумм берутся их остатки, и вот там повторы появляются обязательно — остатков всего семь, а префиксов тридцать один. Именно из-за этих повторов там и нужен счётчик.

EN
pre = [0]
for v in a:
    pre.append(pre[-1] + v)
print(len(set(pre)))    # 31

Answer: 31.

This can be seen without code

Every array element is strictly positive, so the sequence of prefix sums is strictly increasing. Therefore all 31 values are distinct, and there is nothing to compute.

Looking at the structure of the data before calculating saves more exam time than any code optimization.

Where this leads

Strictly increasing prefixes mean that in bridge problem b1104, each sum occurs at most once. In final problem y1101, the prefix sums are replaced by their remainders, which must repeat: there are only seven possible remainders but thirty-one prefixes. These repetitions are exactly why a counter is needed there.

уверенность1 — угадал, 5 — уверен полностью
B1104Базаступень 3обязательнаяАлгоритмыавторская · мост к y1101
RU

Для массива из задачи w1101 найдите количество непустых подотрезков (подряд идущих участков), сумма которых равна ровно 36. Два подотрезка считаются разными, если различаются парой границ, даже если наборы значений в них совпадают.

EN

For the array from problem w1101, find the number of nonempty subarrays, that is, contiguous segments, whose sum is exactly 36. Two subarrays are distinct if their pairs of endpoints differ, even when the sequences of values within them coincide.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$) и $S$, во второй — $n$ целых чисел (бывают нули и отрицательные — окно здесь не спасёт). Вывод. Количество непустых подотрезков с суммой ровно $S$.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$) and $S$; the second holds $n$ integers (zeros and negatives allowed, so a window will not work). Output. The number of non-empty subarrays whose sum is exactly $S$.

ВыводOutput
Подсказка / Hint
RU

Сумма на отрезке — это разность двух префиксных сумм. Значит вопрос «сумма равна 36» превращается в вопрос про пары префиксов с заданной разностью — а пары считает счётчик.

EN

A subarray sum is the difference of two prefix sums. Thus “the sum equals 36” becomes a question about pairs of prefixes with a given difference, and a counter can count such pairs.

Решение / Solution
RU

Шаг 1. Переписать условие через префиксы. Сумма на участке от $l+1$ до $r$ равна $S_r - S_l$. Условие «сумма равна 36» значит $S_l = S_r - 36$.

Шаг 2. Идти по правым концам и спрашивать счётчик. Для каждого $r$ нужно узнать, сколько прежних префиксов равны $S_r - 36$. Это тот же вопрос «сколько раз уже встречалось нужное значение», что и в b1101.

from collections import Counter
c = Counter({0: 1})      # пустой префикс тоже участвует
s = 0; total = 0
for v in a:
    s += v
    total += c[s - 36]   # сколько прежних префиксов дают нужную разность
    c[s] += 1
print(total)             # 10

Ответ: 10.

c[0] = 1 — не украшение

Пустой префикс $S_0 = 0$ обязан лежать в счётчике до цикла, иначе потеряются все подотрезки, начинающиеся с первого элемента. Здесь такой ровно один — это первые девять элементов, их сумма как раз 36, — и без единицы в счётчике ответ был бы 9. Код при этом выглядит правильным. Это ошибка на единицу в чистом виде.

Почему тут годится ещё и окно

Все элементы положительны, поэтому сумма участка растёт вместе с правым концом, и ту же задачу решает окно из приёма 3 урока: правый конец добавляет, левый догоняет, пока сумма больше 36. Это второй независимый способ получить 10, и его стоит написать для проверки.

Но в финале y1101 окно уже не спасёт: там условие не «сумма равна», а «сумма делится», и монотонности по правому концу нет никакой. Работает только счётчик — поэтому учиться надо на нём.

EN

Step 1. Rewrite the condition using prefix sums. The sum from position $l+1$ through $r$ is $S_r - S_l$. The condition that this sum equals 36 is equivalent to $S_l = S_r - 36$.

Step 2. Scan over right endpoints and query a counter. For each $r$, determine how many previous prefix sums equal $S_r - 36$. This is the same “how many times has the required value occurred?” query as in b1101.

from collections import Counter
c = Counter({0: 1})      # the empty prefix counts too
s = 0; total = 0
for v in a:
    s += v
    total += c[s - 36]   # previous prefixes with the required difference
    c[s] += 1
print(total)             # 10

Answer: 10.

c[0] = 1 is essential

The empty prefix $S_0 = 0$ must be in the counter before the loop. Otherwise, every subarray beginning with the first element is missed. Exactly one such subarray occurs here: the first nine elements sum to 36. Without the initial count of one, the answer would be 9 even though the code would look correct. This is a classic off-by-one error.

Why a sliding window also works here

Every element is positive, so a segment's sum increases as its right endpoint advances. The sliding-window technique from Lesson 3 also solves the problem: add at the right and move the left endpoint forward while the sum exceeds 36. This is an independent way to obtain 10 and is worth implementing as a check.

A window will not help in final problem y1101: there the condition is divisibility, not equality to a fixed sum, so there is no monotonicity in the right endpoint. Only the counter works, which is why this is the method to practice.

уверенность1 — угадал, 5 — уверен полностью
B1105Базаступень 3Алгоритмыавторская · мост к s1101
RU

Дана партия из восьми геномов; каждый геном — целое число меньше 64, то есть укладывается в шесть двоичных разрядов:

[12, 21, 32, 44, 48, 57, 59, 63]

Найдите наибольший возможный XOR пары геномов, стоящих на разных позициях.

EN

A batch contains eight genomes, each represented by an integer less than 64 and therefore fitting into six binary digits:

[12, 21, 32, 44, 48, 57, 59, 63]

Find the largest possible XOR of two genomes at distinct positions.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($2 \le n \le 10^5$), во второй — $n$ целых чисел $0 \le a_i < 2^{30}$. Вывод. Наибольший $a_i \oplus a_j$ по парам разных позиций.

EN

Input. The first line holds $n$ ($2 \le n \le 10^5$); the second holds $n$ integers $0 \le a_i < 2^{30}$. Output. The largest $a_i \oplus a_j$ over pairs of different positions.

ВыводOutput
Подсказка / Hint
RU

Наибольший XOR почти никогда не даёт пара с самым большим числом. Иди по разрядам от старшего к младшему и на каждом задавай один вопрос: можно ли поставить в этот разряд единицу, то есть найдётся ли пара чисел, у которых он различается.

EN

The largest XOR almost never comes from a pair containing the largest number. Work from the most significant bit to the least significant. At each bit ask whether it can be set to one, that is, whether there is a pair of numbers whose bits differ there.

Решение / Solution
RU

Шаг 1. Старший разряд. Числа шестибитные, старший разряд — это 32. С ним идут $32, 44, 48, 57, 59, 63$, без него — $12$ и $21$. Обе группы непусты, значит можно взять по числу из каждой, и в старшем разряде XOR будет единица: ответ не меньше $100000_2 = 32$.

Шаг 2. Следующий разряд — тем же вопросом. Проверяем, достижимо ли $110000_2$. Отбросим четыре младших разряда, от каждого числа останутся два старших бита: $12 \to 00$, $21 \to 01$, $32 \to 10$, $44 \to 10$, $48 \to 11$, а $57, 59, 63 \to 11$. Нужна пара с XOR укороченных чисел, равным $11_2$: подходят $00$ и $11$, то есть 12 и 48. Единица остаётся.

Шаг 3. Остальные разряды. Вопрос каждый раз один и тот же — «есть ли пара укороченных чисел, дающая в XOR нужное значение», а это вопрос «встречалось ли нужное значение» из b1101, только вместо суммы XOR:

G = [12, 21, 32, 44, 48, 57, 59, 63]
ans = 0
for bit in range(5, -1, -1):
    cand = ans | (1 << bit)                     # пробуем поставить единицу
    pref = {v >> bit for v in G}                # числа без младших разрядов
    if any((p ^ (cand >> bit)) in pref for p in pref):
        ans = cand                              # пара нашлась, единица остаётся
print(ans)                                      # 60

Ответ собирается по разрядам так: $100000 \to 110000 \to 111000 \to 111100$, а на двух младших разрядах подходящей пары уже нет, и они остаются нулями.

Ответ: 60, это $12 \oplus 48$: $12 = 001100_2$, $48 = 110000_2$, разряды нигде не совпадают, кроме двух младших.

Самое большое число — не самая лучшая пара

Начинать с 63 бесполезно: $63 \oplus 12 = 51$, $63 \oplus 48 = 15$. XOR — не разность, и «побольше с поменьше» здесь ничего не значит. Второй результат тоже даёт пара без максимума: $21 \oplus 44 = 57$.

Куда это ведёт

В финале s1101 спрашивают обратное — минимальный XOR пары. Спуск по разрядам тот же, меняется только направление выбора: для максимума на каждом шаге нужен партнёр с противоположным битом, для минимума — с таким же. Там же этот спуск оформляется деревом (бором), потому что чисел не восемь, а $2\cdot10^{5}$, и перебрать все пары нельзя.

Проверка: пар здесь всего $\binom{8}{2} = 28$, переберите их и убедитесь, что максимум действительно 60. Так делают и на экзамене — маленький вход считается наивно и служит тестом для быстрого алгоритма.

EN

Step 1. The most significant bit. The numbers have six bits, so the most significant bit has value 32. The numbers $32, 44, 48, 57, 59, 63$ contain it, while $12$ and $21$ do not. Both groups are nonempty, so one number can be taken from each and the leading XOR bit can be one. Thus the answer is at least $100000_2 = 32$.

Step 2. Ask the same question about the next bit. Check whether $110000_2$ is attainable. Discard the four least significant bits, leaving the two-bit prefixes $12 \to 00$, $21 \to 01$, $32 \to 10$, $44 \to 10$, $48 \to 11$, and $57, 59, 63 \to 11$. We need two prefixes whose XOR is $11_2$. The pair $00,11$, corresponding to 12 and 48, works, so the second bit remains one.

Step 3. The remaining bits. At every step, ask the same question: is there a pair of truncated numbers producing the required XOR? This is the “has the required value occurred?” query from b1101, with XOR in place of addition:

G = [12, 21, 32, 44, 48, 57, 59, 63]
ans = 0
for bit in range(5, -1, -1):
    cand = ans | (1 << bit)                     # try setting this bit
    pref = {v >> bit for v in G}                # numbers without lower bits
    if any((p ^ (cand >> bit)) in pref for p in pref):
        ans = cand                              # a pair exists, keep the bit
print(ans)                                      # 60

The answer is built bit by bit as $100000 \to 110000 \to 111000 \to 111100$. No suitable pair exists for either of the last two bits, so they remain zero.

Answer: 60, attained by $12 \oplus 48$: $12 = 001100_2$ and $48 = 110000_2$; their bits differ everywhere except in the last two positions.

The largest number need not form the best pair

Starting with 63 is unhelpful: $63 \oplus 12 = 51$ and $63 \oplus 48 = 15$. XOR is not a difference, so pairing a large number with a small one has no special meaning here. Even the second-best result comes from a pair excluding the maximum: $21 \oplus 44 = 57$.

Where this leads

Final problem s1101 asks for the opposite quantity, the minimum XOR of a pair. The bitwise descent is the same, but the choice is reversed: to maximize, seek a partner with the opposite bit at each step; to minimize, seek the same bit. There the descent is implemented as a binary trie because there are $2\cdot10^{5}$ numbers rather than eight, so enumerating all pairs is impossible.

There are only $\binom{8}{2} = 28$ pairs here. Enumerate them to verify that the maximum really is 60. On an exam, a small input can be solved naively and used as a test for the fast algorithm.

уверенность1 — угадал, 5 — уверен полностью
B1106Базаступень 3обязательнаяАлгоритмыавторская · мост к y1103
RU

Дана строка mississippi (11 символов). Найдите длину самой длинной её подстроки (подряд идущих символов), в которой встречается не более двух различных букв.

EN

Consider the 11-character string mississippi. Find the length of its longest substring, that is, its longest contiguous segment, containing at most two distinct letters.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. Одна строка из строчных латинских букв, длина от 1 до $10^5$. Вывод. Длина самой длинной подстроки, в которой не более двух различных букв.

EN

Input. One line of lowercase Latin letters, length from 1 to $10^5$. Output. The length of the longest substring with at most two distinct letters.

ВыводOutput
Подсказка / Hint
RU

Окно: правый конец добавляет букву, а пока различных букв стало больше двух, левый конец догоняет и выбрасывает буквы из окна. Считать буквы в окне удобно словарём.

EN

Use a sliding window. Its right endpoint adds a letter. Whenever the number of distinct letters exceeds two, advance the left endpoint and remove letters from the window. Store window frequencies in a dictionary.

Решение / Solution
RU

Состояние окна — словарь «буква — сколько её сейчас внутри». Правый конец добавляет единицу, левый вычитает; ключ с нулём удаляем, чтобы len(cnt) было честным числом различных букв.

from collections import Counter
s = "mississippi"
cnt = Counter(); left = 0; best = 0
for right, ch in enumerate(s):
    cnt[ch] += 1
    while len(cnt) > 2:            # условие сломалось — двигаем левую границу
        cnt[s[left]] -= 1
        if cnt[s[left]] == 0:
            del cnt[s[left]]
        left += 1
    best = max(best, right - left + 1)
print(best)                        # 7

Ответ: 7 — подстрока ississi, в ней только буквы i и s.

Проверка вторым способом. Подстрок всего $\frac{11\cdot12}{2} = 66$, поэтому годится и полный перебор: для каждой пары границ построить set и посмотреть на его размер. Он тоже даёт 7, но стоит $O(n^3)$ против $O(n)$ у окна — на строке из $10^5$ символов разница уже непреодолимая.

Что здесь ровно то же, что в мини-тесте

Скелет в y1103 дословно такой же: правый конец ведёт, левый догоняет, ответ обновляется на каждом шаге, обе границы идут только вперёд.

Отличается только состояние окна и условие выхода: здесь «различных букв не больше двух» и словарь количеств, там «все буквы различны» и словарь последних позиций. Сначала решается вопрос «что я храню про окно», и лишь потом пишется цикл.

EN

The window state is a dictionary mapping each letter to its current frequency. The right endpoint increments a count and the left endpoint decrements one. Delete a key when its count reaches zero so that len(cnt) really is the number of distinct letters.

from collections import Counter
s = "mississippi"
cnt = Counter(); left = 0; best = 0
for right, ch in enumerate(s):
    cnt[ch] += 1
    while len(cnt) > 2:            # condition breaks — move the left boundary
        cnt[s[left]] -= 1
        if cnt[s[left]] == 0:
            del cnt[s[left]]
        left += 1
    best = max(best, right - left + 1)
print(best)                        # 7

Answer: 7, attained by the substring ississi, which contains only i and s.

Check by a second method. There are only $\frac{11\cdot12}{2} = 66$ substrings, so exhaustive enumeration also works: build a set for each pair of endpoints and inspect its size. This also gives 7, but costs $O(n^3)$ rather than the window's $O(n)$ time. For a string of length $10^5$, the difference is prohibitive.

What is identical in the mini-test

The skeleton in y1103 is literally the same: the right endpoint leads, the left endpoint catches up, the answer is updated at every step, and both endpoints move only forward.

Only the state and validity condition differ. Here we maintain letter counts and require at most two distinct letters. There we maintain last positions and require all letters to be distinct. Decide first what information the window must store, and only then write the loop.

уверенность1 — угадал, 5 — уверен полностью
B1107Базаступень 3обязательнаяАлгоритмыавторская · мост к y1102
RU

Есть шесть досок целой длины (в сантиметрах):

[11, 25, 7, 40, 18, 9]

Их режут поперёк на куски одинаковой целой длины $L$; остатки короче $L$ выбрасываются, склеивать куски нельзя. Нужно получить не менее 12 кусков.

Найдите максимальное целое $L$, при котором это возможно.

EN

There are six boards of integer lengths, measured in centimeters:

[11, 25, 7, 40, 18, 9]

They are cut crosswise into pieces of the same integer length $L$. Remainders shorter than $L$ are discarded, and pieces cannot be joined. At least 12 pieces are required.

Find the largest integer $L$ for which this is possible.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$) и $m$, во второй — длины досок $1 \le p_i \le 10^9$; гарантируется $1 \le m \le \sum p_i$. Вывод. Наибольшее целое $L$, при котором выходит не менее $m$ кусков.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$) and $m$; the second holds board lengths $1 \le p_i \le 10^9$, with $1 \le m \le \sum p_i$ guaranteed. Output. The largest integer $L$ that yields at least $m$ pieces.

ВыводOutput
Подсказка / Hint
RU

Проверить конкретное $L$ легко: из доски длины $p$ выходит $\lfloor p/L\rfloor$ кусков. И эта проверка монотонна по $L$ — только в другую сторону, чем в эталонной задаче урока.

EN

For a fixed $L$, a board of length $p$ yields $\lfloor p/L\rfloor$ pieces. This predicate is monotone in $L$, but in the opposite direction from the model problem in the lesson.

Решение / Solution
RU

Шаг 1. Предикат. При длине куска $L$ всего кусков получается

$$\text{cuts}(L) = \sum_i \left\lfloor \frac{p_i}{L} \right\rfloor$$

и годятся те $L$, у которых $\text{cuts}(L) \ge 12$.

Шаг 2. Монотонность. Чем длиннее кусок, тем их меньше: cuts не возрастает. Значит годные $L$ образуют отрезок $[1, L_0]$, и надо найти его правый конец.

Шаг 3. Зеркальный шаблон. Для максимума середина берётся с округлением вверх, иначе цикл зациклится на паре соседних значений:

p = [11, 25, 7, 40, 18, 9]
def cuts(L):
    return sum(x // L for x in p)

lo, hi = 1, max(p)                 # lo = 1 заведомо годится
while lo < hi:
    mid = (lo + hi + 1) // 2       # ВВЕРХ, а не вниз
    if cuts(mid) >= 12: lo = mid   # годится — граница не левее mid
    else:               hi = mid - 1
print(lo)                          # 8

Шаг 4. Проверка соседа. При $L = 8$: $1 + 3 + 0 + 5 + 2 + 1 = 12 \ge 12$ ✓. При $L = 9$: $1 + 2 + 0 + 4 + 2 + 1 = 10 < 12$ ✗. Значит 8 — именно граница.

Ответ: 8.

Три места, где теряют ответ

Округление. Здесь целая часть вниз — кусок короче $L$ не считается. В финале y1102 наоборот, округление вверх: неполный час всё равно потрачен. Направление округления определяется условием, а не привычкой.

Середина. В зеркальном шаблоне mid = (lo + hi + 1) // 2. С обычным // 2 при lo = hi - 1 середина совпадёт с lo, присваивание lo = mid ничего не изменит и цикл зациклится.

Нижняя граница. lo = 1, а не 0: делить на ноль нельзя, и $L = 0$ не имеет смысла.

EN

Step 1. Predicate. For piece length $L$, the total number of pieces is

$$\text{cuts}(L) = \sum_i \left\lfloor \frac{p_i}{L} \right\rfloor$$

and a value of $L$ is feasible when $\text{cuts}(L) \ge 12$.

Step 2. Monotonicity. Longer pieces produce fewer pieces, so cuts is nonincreasing. The feasible values therefore form an interval $[1,L_0]$, and we need its right endpoint.

Step 3. Mirrored template. When searching for the maximum, round the midpoint upward; otherwise the loop may stall on two adjacent values:

p = [11, 25, 7, 40, 18, 9]
def cuts(L):
    return sum(x // L for x in p)

lo, hi = 1, max(p)                 # lo = 1 is certainly feasible
while lo < hi:
    mid = (lo + hi + 1) // 2       # round UP, not down
    if cuts(mid) >= 12: lo = mid   # feasible — boundary is not left of mid
    else:               hi = mid - 1
print(lo)                          # 8

Step 4. Check the adjacent value. For $L = 8$, the number of pieces is $1 + 3 + 0 + 5 + 2 + 1 = 12 \ge 12$ ✓. For $L = 9$, it is $1 + 2 + 0 + 4 + 2 + 1 = 10 < 12$ ✗. Therefore 8 is exactly the boundary.

Answer: 8.

Three places where the answer is lost

Rounding. Here integer division rounds down because a remainder shorter than $L$ is discarded. In final problem y1102, the rounding is upward because a partial hour is still spent. The problem statement, not habit, determines the direction of rounding.

Midpoint. The mirrored template uses mid = (lo + hi + 1) // 2. With ordinary // 2, when lo = hi - 1, the midpoint equals lo; assigning lo = mid changes nothing and the loop never terminates.

Lower bound. Use lo = 1, not 0: division by zero is invalid, and a length of zero is meaningless.

уверенность1 — угадал, 5 — уверен полностью

Уровень YMLS

решено 0 из 3

Целевая сложность вступительного экзамена. Ответ — число.

Y1101Уровень YMLSступень 4минимумАлгоритмыуровень YMLS · префиксы по модулю
RU

Для массива из задачи w1101 найдите количество непустых подотрезков (подряд идущих участков), сумма которых делится на 7. Два подотрезка считаются разными, если различаются парой границ.

В настоящей постановке этой задачи $n \le 2\cdot10^{5}$ — перебор всех подотрезков там не проходит по времени; здесь $n = 30$, чтобы ответ можно было проверить перебором. Ограничение прочитано — сложность решения назови вслух до того, как писать код.

EN

For the array from problem w1101, find the number of nonempty subarrays, that is, contiguous segments, whose sum is divisible by 7. Two subarrays are distinct if their pairs of endpoints differ.

In the full version of this problem, $n \le 2\cdot10^{5}$, so enumerating every subarray is too slow. Here $n = 30$, allowing the answer to be verified by exhaustive search. Read the constraint and state the target complexity aloud before writing code.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$) и $k$ ($1 \le k \le 10^9$), во второй — $n$ целых чисел (бывают отрицательные). Вывод. Количество непустых подотрезков, сумма которых делится на $k$.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$) and $k$ ($1 \le k \le 10^9$); the second holds $n$ integers (negatives allowed). Output. The number of non-empty subarrays whose sum is divisible by $k$.

ВыводOutput
Подсказка / Hint
RU

Сумма на отрезке $(l, r]$ равна $S_r - S_l$. Когда разность делится на 7?

EN

The sum on $(l,r]$ is $S_r-S_l$. When is this difference divisible by 7?

Решение / Solution
RU

Ключевая идея. Сумма на $(l, r]$ делится на 7 тогда и только тогда, когда $S_r$ и $S_l$ дают одинаковый остаток при делении на 7. Значит вопрос про отрезки превратился в вопрос про пары префиксов с равным остатком, а такие пары считает счётчик — ровно как в мосте b1104, только там сравнивались сами суммы, а здесь их остатки.

from collections import Counter
c = Counter({0: 1})     # пустой префикс тоже участвует
s = 0; total = 0
for v in a:
    s = (s + v) % 7
    total += c[s]       # все прежние префиксы с тем же остатком
    c[s] += 1
print(total)            # 56

Ответ: 56.

Почему c[0] = 1 изначально

Пустой префикс $S_0 = 0$ обязан участвовать, иначе потеряются все подотрезки, начинающиеся с первого элемента. Это классическая ошибка на единицу: код выглядит правильно, ответ занижен, и понять причину без разбора трудно.

Почему счётчик здесь обязателен

В b1104 префиксные суммы строго возрастали, поэтому каждое значение встречалось не больше одного раза, и счётчик отвечал «нуль или один». Остатков всего семь, а префиксов тридцать один, поэтому одинаковые остатки встречаются по многу раз — и вопрос «сколько прежних» становится настоящим.

Сложность $O(n)$ по времени и $O(k)$ по памяти, где $k = 7$. Наивный перебор всех подотрезков был бы $O(n^2)$, а с пересчётом суммы каждый раз — даже $O(n^3)$.

EN

Key idea. The sum on $(l,r]$ is divisible by 7 if and only if $S_r$ and $S_l$ have the same remainder modulo 7. Thus a question about subarrays becomes a question about pairs of prefix sums with equal remainders. A counter counts these pairs, just as in b1104; that problem compared the sums themselves, while this one compares their remainders.

from collections import Counter
c = Counter({0: 1})     # the empty prefix counts too
s = 0; total = 0
for v in a:
    s = (s + v) % 7
    total += c[s]       # all earlier prefixes with the same remainder
    c[s] += 1
print(total)            # 56

Answer: 56.

Why initialize c[0] = 1?

The empty prefix $S_0 = 0$ must be included; otherwise every subarray beginning with the first element is missed. This is a classic off-by-one error: the code looks correct, but the answer is too small and the cause is difficult to see without tracing it.

Why a counter is essential here

In b1104, prefix sums were strictly increasing, so each value occurred at most once and the counter returned only zero or one. Here there are only seven remainders but thirty-one prefix sums, so equal remainders occur many times and “how many previous ones?” becomes a genuine counting question.

The complexity is $O(n)$ time and $O(k)$ space, where $k=7$. Naively enumerating every subarray takes $O(n^2)$ time, or even $O(n^3)$ if each sum is recomputed from scratch.

уверенность1 — угадал, 5 — уверен полностью
Y1102Уровень YMLSступень 4минимумАлгоритмыуровень YMLS · бинпоиск по ответу
RU

Есть пять куч бананов размерами $[30, 11, 23, 4, 20]$ и $h = 6$ часов. За один час можно съесть не более $k$ бананов из одной кучи; если в куче осталось меньше $k$, час всё равно тратится целиком, и перейти к другой куче в этот же час нельзя.

Найдите минимальное целое $k$, при котором все кучи будут съедены за $h$ часов.

EN

There are five piles of bananas of sizes $[30, 11, 23, 4, 20]$ and $h = 6$ available hours. During one hour, at most $k$ bananas may be eaten from one pile. If fewer than $k$ bananas remain, the full hour is still used, and no other pile may be started during that hour.

Find the smallest integer $k$ for which all piles can be eaten within $h$ hours.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($1 \le n \le 10^5$) и $h$ ($n \le h \le 10^9$), во второй — размеры куч $1 \le p_i \le 10^9$. Вывод. Наименьшее целое $k$, при котором все кучи съедены за $h$ часов.

EN

Input. The first line holds $n$ ($1 \le n \le 10^5$) and $h$ ($n \le h \le 10^9$); the second holds pile sizes $1 \le p_i \le 10^9$. Output. The smallest integer $k$ that finishes all piles within $h$ hours.

ВыводOutput
Подсказка / Hint
RU

Проверить конкретное $k$ легко, и эта проверка монотонна. Дальше — шаблон эталонной задачи урока, только предикат другой.

EN

Checking a fixed $k$ is easy, and the predicate is monotone. Apply the template from the model problem in the lesson with a different predicate.

Решение / Solution
RU

Шаг 1. Что ищем. «Минимальное $k$, при котором …» — признак бинарного поиска по ответу. Ищем не элемент массива куч, а само число $k$.

Шаг 2. Предикат. При скорости $k$ на кучу размера $p$ уходит $\lceil p/k\rceil$ часов — неполный час тоже потрачен:

$$\text{hours}(k) = \sum_i \left\lceil \frac{p_i}{k}\right\rceil$$

Шаг 3. Монотонность. Чем больше $k$, тем меньше часов. Значит годные значения $k$ образуют луч $[k_0, +\infty)$, и надо найти его левую границу.

Шаг 4. Границы. $\text{lo} = 1$ — меньше есть нельзя; $\text{hi} = \max p_i = 30$ заведомо годится: при такой скорости каждая куча съедается за один час, всего пять часов из шести.

piles = [30, 11, 23, 4, 20]; h = 6

def hours(k):
    return sum(-(-p // k) for p in piles)    # -(-a//b) = округление вверх

lo, hi = 1, max(piles)
while lo < hi:
    mid = (lo + hi) // 2
    if hours(mid) <= h: hi = mid       # подошло — граница не правее
    else:               lo = mid + 1   # не подошло — mid точно мал
print(lo)                              # 23

Шаг 5. Проверка соседа. При $k = 23$ часы складываются в $2+1+1+1+1 = 6 \le 6$ ✓. При $k = 22$ — в $2+1+2+1+1 = 7 > 6$ ✗. Значит 23 — граница, а не «примерно то».

Ответ: 23.

Чем эта задача отличается от моста b1107

Там искали максимум и делили нацело вниз, здесь ищут минимум и округляют вверх. Шаблон соответственно обычный, а не зеркальный: hi = mid и lo = mid + 1, середина без единицы.

Направление округления читается прямо из условия: «час тратится целиком» — вверх, «остаток короче куска выбрасывается» — вниз. Перепутанное округление даёт число, отличающееся от верного на единицу, и никакого сигнала об ошибке.

EN

Step 1. Identify the search variable. The phrase “smallest $k$ such that” signals binary search on the answer. We are searching for $k$ itself, not for an element of the array of pile sizes.

Step 2. Predicate. At rate $k$, a pile of size $p$ takes $\lceil p/k\rceil$ hours because a partial hour is still spent:

$$\text{hours}(k) = \sum_i \left\lceil \frac{p_i}{k}\right\rceil$$

Step 3. Monotonicity. As $k$ increases, the required time decreases. Hence the feasible values form the ray $[k_0,+\infty)$, and we need its left endpoint.

Step 4. Bounds. Set $\text{lo}=1$, since smaller values are impossible. Set $\text{hi}=\max p_i=30$, which is certainly feasible: at this rate each pile is finished in one hour, using five of the six hours.

piles = [30, 11, 23, 4, 20]; h = 6

def hours(k):
    return sum(-(-p // k) for p in piles)    # -(-a//b) = ceiling division

lo, hi = 1, max(piles)
while lo < hi:
    mid = (lo + hi) // 2
    if hours(mid) <= h: hi = mid       # feasible — boundary is not to the right
    else:               lo = mid + 1   # infeasible — mid is definitely too small
print(lo)                              # 23

Step 5. Check the adjacent value. For $k = 23$, the hours sum to $2+1+1+1+1 = 6 \le 6$ ✓. For $k = 22$, they sum to $2+1+2+1+1 = 7 > 6$ ✗. Therefore 23 is the exact boundary, not merely an approximation.

Answer: 23.

How this differs from bridge problem b1107

There we sought a maximum and rounded down; here we seek a minimum and round up. Accordingly, this is the ordinary rather than mirrored template: use hi = mid, lo = mid + 1, and no added one in the midpoint.

The direction of rounding comes directly from the statement: “the full hour is used” means round up, while “a remainder shorter than the piece is discarded” means round down. The wrong direction usually gives an answer off by one without any obvious warning.

уверенность1 — угадал, 5 — уверен полностью
Y1104Уровень YMLSступень 4минимумАлгоритмыуровень YMLS
RU

Для массива из задачи w1101 найдите сумму пяти наибольших элементов. Повторы учитываются: если одно и то же значение встречается несколько раз, оно и берётся столько раз, сколько попало в пятёрку.

EN

For the array from problem w1101, find the sum of its five largest elements. Repetitions count: if the same value occurs several times, include it as many times as it appears among the top five elements.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ и $k$ ($1 \le k \le n \le 10^5$), во второй — $n$ целых чисел. Вывод. Сумма $k$ наибольших элементов, повторы учитываются.

EN

Input. The first line holds $n$ and $k$ ($1 \le k \le n \le 10^5$); the second holds $n$ integers. Output. The sum of the $k$ largest elements, counting repeats.

ВыводOutput
Подсказка / Hint
RU

Полная сортировка избыточна — достаточно кучи размера $k$.

EN

Sorting the full array is unnecessary; a heap of size $k$ is sufficient.

Решение / Solution
RU
import heapq
print(sum(heapq.nlargest(5, a)))   # 43

Ответ: 43 — это $9 + 9 + 9 + 8 + 8$. Девятка встречается в массиве трижды, восьмёрка — тоже трижды, и в пятёрку крайних попадают три девятки и две восьмёрки.

Это тот же проход, что в мосте b1102: куча размера 5 идёт по массиву и держит пятёрку лучших. Там спрашивали её вершину — пятый по величине элемент, здесь нужна сумма всей пятёрки, поэтому вершину брать не надо, а надо сложить содержимое кучи.

Где здесь теряют ответ

Если прочитать условие как «пять наибольших различных значений», получится $9 + 8 + 7 + 6 + 5 = 35$ — другое число. Условие говорит про элементы, а не про значения, поэтому повторы берутся столько раз, сколько их есть.

Три ответа, которые надо назвать на собеседовании

Сортировка — $O(n\log n)$, просто и всегда работает. Куча размера $k$ — $O(n\log k)$, заметно быстрее при $k \ll n$. Quickselect — $O(n)$ в среднем; «медиана медиан» даёт $O(n)$ в худшем случае.

Назвать все три — сильный ход. Он показывает, что ты видишь пространство решений, а не одно заученное.

EN
import heapq
print(sum(heapq.nlargest(5, a)))   # 43

Answer: 43, since $9 + 9 + 9 + 8 + 8 = 43$. The value 9 occurs three times and 8 also occurs three times, so the top five elements contain three 9s and two 8s.

This is the same pass as in bridge problem b1102: a heap of size 5 traverses the array and retains the five best elements. That problem asks for the heap's top, the fifth-largest element. Here we need the sum of all five elements, so we sum the entire heap rather than reading its top.

How the wrong answer arises

If the statement is misread as asking for the five largest distinct values, the result is $9 + 8 + 7 + 6 + 5 = 35$. The problem asks about elements, not distinct values, so repetitions count as many times as they occur.

Three solutions to mention in an interview

Sorting: $O(n\log n)$, simple and universally applicable. A heap of size $k$: $O(n\log k)$, substantially faster when $k \ll n$. Quickselect: $O(n)$ expected time; median of medians gives $O(n)$ worst-case time.

Naming all three is valuable: it shows that you see the solution space rather than one memorized method.

уверенность1 — угадал, 5 — уверен полностью

Уровень ШАД

решено 0 из 1

Выше, чем требуется. Берём только там, где тема реально встречалась на их экзаменах.

S1101Уровень ШАДступень 4АлгоритмыОлимпиада ШАД 2025, задача «Похожие геномы»
RU

Мерой похожести двух вирусов служит побитовое исключающее ИЛИ (XOR) их геномов: чем меньше XOR, тем более похожи вирусы.

В базе лежат геномы

[38, 18, 7, 52, 13, 25, 60, 3, 44, 29]

Найдите наименьший возможный XOR пары геномов, стоящих на разных позициях.

EN

The similarity of two viruses is measured by the bitwise exclusive OR (XOR) of their genomes: the smaller the XOR, the more similar the viruses.

The database contains the genomes

[38, 18, 7, 52, 13, 25, 60, 3, 44, 29]

Find the smallest possible XOR of two genomes at distinct positions.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. В первой строке $n$ ($2 \le n \le 10^5$), во второй — $n$ целых чисел $0 \le a_i < 2^{30}$. Вывод. Наименьший $a_i \oplus a_j$ по парам разных позиций.

EN

Input. The first line holds $n$ ($2 \le n \le 10^5$); the second holds $n$ integers $0 \le a_i < 2^{30}$. Output. The smallest $a_i \oplus a_j$ over pairs of different positions.

ВыводOutput
Подсказка / Hint
RU

Для десяти чисел хватит перебора сорока пяти пар — приём из b1101, только вместо суммы XOR. Быстрый ход — тот же спуск по разрядам, что в мосте b1105, но в обратную сторону. А дальше подумай, как отвечать на такой запрос, если чисел $2 \cdot 10^5$ и они добавляются по одному.

EN

With ten numbers, enumerating all forty-five pairs is enough; this is the technique from b1101, with XOR instead of addition. The fast approach uses the same bitwise descent as bridge problem b1105, but in the opposite direction. Then consider how to answer the query if there are $2 \cdot 10^5$ numbers arriving one by one.

Решение / Solution
RU

Ответ для наших данных: 4 — пара $7$ и $3$: $7 \oplus 3 = 0111_2 \oplus 0011_2 = 0100_2 = 4$.

from itertools import combinations
print(min(x ^ y for x, y in combinations(G, 2)))   # 4

Перебор пар — это $O(n^2)$, здесь всего 45 пар. На олимпиадных ограничениях ($n$ до $2\cdot10^5$, числа до $2^{30}$) он не проходит, и нужен другой подход.

Правильное решение — префиксное дерево (бор) на битах.

Храним двоичные представления чисел в дереве как строки длины $K = 30$, от старших разрядов к младшим. При добавлении нового числа $X$ делаем два действия:

  1. Ищем в боре число $Y$, дающее минимальный XOR с $X$. Спускаемся от корня; на каждой глубине пытаемся пойти по тому же биту, что у $X$ — тогда в этом разряде XOR даст ноль. Если такого перехода нет, идём по единственному имеющемуся.
  2. Вставляем $X$ в бор.

Ответ поддерживаем как минимум по всем добавлениям.

Почему жадный спуск корректен. Пусть на глубине $d$ можно пойти двумя путями. Совпадение бита даёт в этом разряде ноль, несовпадение — единицу, то есть вклад $2^{K-d}$. Но по пункту блока «Мост» один старший разряд перевешивает все младшие вместе взятые, поэтому совпадение в старшем разряде выгоднее любого выигрыша во всех младших. Жадность оптимальна.

Сложность: $O(NK)$ по времени и памяти, где $K$ — число бит.

Проверка третьим способом

Работает правило из блока «Триггеры»: минимальный XOR всегда достигается на паре соседей в отсортированном порядке. Вот его вывод в две строки. Пусть $x < y < z$, и пусть $b$ — самый старший разряд, в котором $x$ и $z$ различаются: в нём у $x$ ноль, у $z$ единица, поэтому $x \oplus z \ge 2^{b}$. Все разряды старше $b$ у $x$ и $z$ совпадают, а $y$ лежит между ними, поэтому в старших разрядах $y$ совпадает с обоими; в самом разряде $b$ у $y$ стоит либо ноль, и тогда $x \oplus y < 2^{b}$, либо единица, и тогда $y \oplus z < 2^{b}$. В обоих случаях какая-то из более тесных пар строго лучше крайней — значит пару, между членами которой лежит третье число, можно не проверять.

Отсортируем: 3, 7, 13, 18, 25, 29, 38, 44, 52, 60 — и проверим только девять соседних пар вместо сорока пяти. Их XOR равны 4, 10, 31, 11, 4, 59, 10, 24, 8; наименьшее значение 4 достигается дважды: $3 \oplus 7 = 4$ и $25 \oplus 29 = 4$. Ответ сошёлся с перебором, и это независимая проверка, а не пересчёт того же самого.

Что забрать

Идея «старший разряд важнее всех младших вместе» — универсальная для битовых задач. Она превращает переборную задачу в жадный спуск по дереву, то есть в то же деление пополам, что и бинарный поиск, только режется не отрезок чисел, а множество кандидатов по очередному биту.

На YMLS такое вряд ли придёт в полном объёме, но сам приём «работать с числами поразрядно, от старших к младшим» вполне может понадобиться.

EN

For the given data, the answer is 4, attained by 7 and 3: $7 \oplus 3 = 0111_2 \oplus 0011_2 = 0100_2 = 4$.

from itertools import combinations
print(min(x ^ y for x, y in combinations(G, 2)))   # 4

Pair enumeration takes $O(n^2)$ time and involves only 45 pairs here. It is too slow under olympiad constraints ($n$ up to $2\cdot10^5$, values below $2^{30}$), so a different approach is required.

The appropriate solution is a binary prefix tree, or binary trie.

Store the binary representations of the numbers in a tree as strings of length $K=30$, from the most significant bit to the least significant. When a new number $X$ arrives, perform two operations:

  1. Find a number $Y$ in the trie minimizing its XOR with $X$. Descend from the root. At each depth, first try the branch with the same bit as $X$, which contributes zero at this position. If that branch does not exist, take the only available branch.
  2. Insert $X$ into the trie.

Maintain the answer as the minimum over all insertions.

Why the greedy descent is correct. Suppose both branches are available at depth $d$. Matching the bit contributes zero at this position, while differing contributes one, with value $2^{K-d}$. One more significant bit outweighs all less significant bits combined, as established in the Bridge section. Therefore matching the more significant bit is preferable to any possible gain below it, and the greedy choice is optimal.

The time and space complexity are $O(NK)$, where $K$ is the number of bits.

A third method for checking

The rule from the Triggers section applies: the minimum XOR is always attained by two adjacent values in sorted order. Here is the proof. Let $x<y<z$, and let $b$ be the most significant bit at which $x$ and $z$ differ. At this bit, $x$ has zero and $z$ has one, so $x\oplus z \ge 2^b$. All bits above $b$ coincide in $x$ and $z$. Since $y$ lies between them, it agrees with both in those higher bits. At bit $b$, either $y$ has zero, giving $x\oplus y < 2^b$, or it has one, giving $y\oplus z < 2^b$. In either case, a closer pair is strictly better than the outer pair. Thus a pair with a third number between its members never needs to be checked.

Sort the values: 3, 7, 13, 18, 25, 29, 38, 44, 52, 60. Check only nine adjacent pairs rather than forty-five. Their XORs are 4, 10, 31, 11, 4, 59, 10, 24, 8. The minimum, 4, is attained twice: $3 \oplus 7 = 4$ and $25 \oplus 29 = 4$. This agrees with exhaustive search and is an independent check.

The takeaway

The principle “a more significant bit outweighs all less significant bits combined” is universal in bitwise problems. It turns an exhaustive search into a greedy tree descent: the same kind of halving as binary search, except that the candidate set is partitioned by the next bit rather than by a numeric interval.

A full-strength version is unlikely on YMLS, but the underlying technique of processing numbers bit by bit, from most significant to least significant, may well be useful.

уверенность1 — угадал, 5 — уверен полностью

Мини-тест под таймером

20 минут

Одна задача, таймер идёт, подсказки и решение не открываются до истечения времени. Это тренировка не математики, а поведения под давлением.

Y1103Уровень YMLSступень 4минимумАлгоритмыуровень YMLS · скользящее окно
RU

Дана строка algorithmsandprogramming (24 символа). Найдите длину самой длинной её подстроки (подряд идущих символов), в которой все символы различны.

В настоящей постановке строка длиной до $2\cdot10^{5}$ символов; здесь 24, чтобы ответ можно было пересчитать руками. Назови сложность и приём до того, как писать код.

EN

Consider the 24-character string algorithmsandprogramming. Find the length of its longest substring, that is, its longest contiguous segment, in which all characters are distinct.

In the full version, the string may contain up to $2\cdot10^{5}$ characters. Here its length is 24, so the answer can be checked by hand. State the technique and complexity before writing code.

Python · решить кодомsolve in code
RU

Программа читает ввод и печатает ответ. «Проверить на тестах» запускает её на тестах задачи: первый — данные из условия (они уже в поле «Ввод»), остальные скрыты, последний большой — на скорость. Прошли все — задача засчитана.

EN

The program reads the input and prints the answer. “Run tests” runs it on the problem’s tests: the first is the statement’s data (already in the Input box), the rest are hidden, and the last one is large to test speed. Pass them all and the problem counts as solved.

RU

Ввод. Одна строка из строчных латинских букв, длина от 1 до $10^5$. Вывод. Длина самой длинной подстроки, в которой все символы различны.

EN

Input. One line of lowercase Latin letters, length from 1 to $10^5$. Output. The length of the longest substring whose characters are all distinct.

ВыводOutput
Подсказка / Hint
RU

Расширяй правую границу окна; когда символ повторился, сдвигай левую границу за его предыдущее вхождение.

EN

Expand the right boundary of a window. When a character repeats, move the left boundary just beyond its previous occurrence.

Решение / Solution
RU

Состояние окна — словарь «символ — его последний индекс». Когда правый конец приносит символ, уже стоящий внутри окна, левая граница перескакивает сразу за его прошлое вхождение: все промежуточные положения заведомо плохи, проверять их незачем.

s = "algorithmsandprogramming"
seen = {}          # символ -> последний индекс
left = 0; best = 0
for right, ch in enumerate(s):
    if ch in seen and seen[ch] >= left:
        left = seen[ch] + 1        # сдвигаем левую границу
    seen[ch] = right
    best = max(best, right - left + 1)
print(best)                        # 13

Ответ: 13 — подстрока lgorithmsandp.

Условие seen[ch] >= left обязательно

Без него левая граница может прыгнуть назад, если символ встречался давно, ещё до текущего окна. Тогда окно расширится за пределы допустимого и ответ будет завышен.

Сложность $O(n)$: каждый из двух указателей проходит строку ровно один раз и никогда не идёт назад. Как только левая граница получила право двигаться назад, ломается и правильность, и линейность — сразу обе.

Проверка ответа за десять секунд

Различных букв в строке ровно 13, значит подстрока без повторов длиннее 13 невозможна в принципе. Ответ упёрся ровно в этот потолок: в подстроке lgorithmsandp встречаются все тринадцать букв по одному разу.

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

EN

The window state is a dictionary mapping each character to its most recent index. When the right endpoint brings in a character already inside the window, move the left endpoint immediately past its previous occurrence. Every intermediate position is invalid, so there is no reason to check it.

s = "algorithmsandprogramming"
seen = {}          # character -> last index
left = 0; best = 0
for right, ch in enumerate(s):
    if ch in seen and seen[ch] >= left:
        left = seen[ch] + 1        # move the left boundary
    seen[ch] = right
    best = max(best, right - left + 1)
print(best)                        # 13

Answer: 13, attained by the substring lgorithmsandp.

The condition seen[ch] >= left is essential

Without it, the left boundary may move backward when the same character occurred long ago, before the current window. The window would then expand beyond the valid range and the answer would be too large.

The complexity is $O(n)$: each of the two pointers traverses the string once and never moves backward. Allowing the left boundary to move backward destroys both correctness and linear complexity at once.

A ten-second answer check

The string contains exactly 13 distinct letters, so no repetition-free substring can have length greater than 13. The answer reaches this upper bound: lgorithmsandp contains all thirteen letters exactly once.

This estimate does not replace a solution, but it catches an answer that is too large immediately and, here, suggests looking for a window containing the string's entire alphabet.

уверенность1 — угадал, 5 — уверен полностью
день закрыт, когда
По условию задачи за 30 секунд называешь вслух приём, сложность и структуру данных, а там, где ограничение на размер входа выписано (b1102, y1101, y1103), читаешь его и называешь допустимую сложность до того, как предлагать решение: десять условий подряд со страницы задач без единой ошибки распознаванияBy the problem statement, name the technique, complexity, and data structure aloud within 30 seconds; where the input-size constraint is written (b1102, y1101, y1103), read it and name the allowed complexity before suggesting a solution: ten consecutive statements from the problem page with no recognition error
Шаблон бинарного поиска по ответу пишешь по памяти за 2 минуты, предикат выносишь отдельной функцией и всегда проверяешь соседа lo - 1: b1107 и y1102 сходятся с первого запускаWrite the binary-search-on-the-answer template from memory in 2 minutes, put the predicate in a separate function, and always check neighbor lo - 1: b1107 and y1102 converge on the first run
Подсчёт подотрезков счётчиком префиксов пишешь за 4 минуты и сам, без напоминания, кладёшь в счётчик пустой префикс: b1104 и y1101 без ошибки на единицуWrite the prefix-counter subarray count in 4 minutes and, without prompting, put the empty prefix into the counter: b1104 and y1101 with no off-by-one error
Окно пишешь так, что левая граница ни разу не уходит назад, и за 15 секунд объясняешь, почему проход остаётся один: w1103, b1106 и мини-тест y1103Write the window so the left boundary never moves backward, and explain in 15 seconds why the pass remains a single pass: w1103, b1106, and mini-test y1103
Просят $k$ крайних — берёшь кучу размера $k$ и вслух называешь $O(n\log k)$ против $O(n\log n)$ (b1102, y1104); появились биты — идёшь по разрядам от старшего (b1105, s1101)When asked for $k$ extremes, use a heap of size $k$ and say $O(n\log k)$ aloud versus $O(n\log n)$ (b1102, y1104); when bits appear, process them from the most significant one (b1105, s1101)
Мини-тест y1103 сдан за 15 минут при отведённых 25, с первого ввода, и все четыре обязательные задачи решены без подсказкиSubmit mini-test y1103 in 15 minutes out of the allotted 25, on the first submission, and solve all four mandatory problems without hints
аудит дня
RU

Раздели ошибки на два типа и запиши каждую. Первый тип — не тот приём: увидел подотрезки и полез перебирать пары, увидел «минимальное такое, что» и стал решать уравнение, взял список там, где нужен был словарь. Второй — приём верный, сломана граница: забыт пустой префикс в счётчике, левая граница окна прыгнула назад, взято округление вниз вместо округления вверх, не проверен сосед после бинарного поиска.

Диагнозы разные. Первый тип лечится блоком «Триггеры»: перечитывать его вслух, пока распознавание не станет мгновенным. Второй — только повторным написанием того же кода с нуля и проверкой на игрушечном примере, где ответ известен руками.

Ошибки второго типа опаснее, чем кажутся: код с ними выглядит правильным и выдаёт число, просто не то. На онлайн-этапе, где принимается только ответ, такая ошибка неотличима от полного незнания темы.

EN

Separate errors into two types and record each one. The first is the wrong technique: you saw subarrays and started enumerating pairs, saw “the minimum such that” and began solving an equation, or chose a list where a dictionary was needed. The second is the right technique with a broken boundary: you forgot the empty prefix in the counter, the window’s left boundary jumped backward, you used floor instead of ceiling, or you did not check the neighbor after binary search.

The diagnoses differ. The first type is treated with the “Triggers” block: reread it aloud until recognition becomes instant. The second requires writing the same code from scratch and checking a small example whose answer you can calculate by hand.

Second-type errors are more dangerous than they look: the code appears correct and returns a number, just the wrong one. In an online stage that accepts only the answer, such an error is indistinguishable from complete ignorance of the topic.