01
Отрезки
«A — это отрезок [a; b], ищем его длину»
Признаки в условии
- «на числовой прямой даны отрезки P, Q…», запись
x ∈ P
- «наименьшую / наибольшую длину отрезка A»
- x — действительное число (не только целое)
Идея
A — это отрезок, поэтому функция принимает его границы: f(a, b, x).
Перебираем пары границ (a, b), проверяем тождественную истинность и среди подходящих берём минимальную или максимальную длину b - a.
Демо-2026 (P=[25;64], Q=[40;115]) даёт длину 24.
Функция выражения (демо-2026)
def seg(L, R, x): # принадлежность точки отрезку [L; R]
return L <= x <= R
def f(a, b, x): # A — это отрезок [a; b]
P = seg(25, 64, x)
Q = seg(40, 115, x)
A = seg(a, b, x)
# (x∈P) → (((x∈Q) ∧ ¬(x∈A)) → ¬(x∈P))
return (not P) or ((not (Q and not A)) or (not P))
Аналитика для больших чисел
Когда границы шестизначные (P=[153697; 780411]…), перебор пар невозможен. Метод в три шага:
- 1. Упрощаем выражение (раскрываем импликации
P → B = ¬P ∨ B) и делим на часть без A и часть с A ((x∈A) или ¬(x∈A)).
- 2. Рисуем на оси, где «часть без A» ложна — это «дыра», за которую отвечает A.
- 3. Закрываем дыру: если A-часть это
(x∈A) — A обязан накрыть дыру; если ¬(x∈A) — A обязан её не задеть (обойти).
Найденный A проверяем кодом-подстановкой (не перебором):
print(all(f(a, b, x) for x in range(L, R))).
Метод на числовой оси — два примера
Условные обозначения: тонкие скобки — отрезки P и Q (ножки касаются границ); жирная скобка — искомый A; полоса на самой прямой — результат выражения без A (зелёное = истина, красное = дыра, за которую отвечает A).
Пример 1 (часть с A = (x∈A) — A накрывает).
Выражение (x∈P) → ((x∈Q) ∨ (x∈A)) упрощаем: ¬P ∨ Q ∨ A. Часть без A это ¬P ∨ Q; она ложна только там, где x входит в P, но не в Q. Эту дыру обязан накрыть A.
A должен накрыть дыру [10; 30] → минимальная длина 20.
Пример 2 (часть с A = ¬(x∈A) — A обходит). Выражение (x∈A) → (x∈P) упрощаем: ¬A ∨ P. Часть без A это P; она ложна везде вне P. На этой дыре нужна ¬(x∈A), то есть A туда заходить нельзя — значит A целиком сидит внутри P.
A не должен задевать дыру (всё вне P) → A ⊆ [10; 50], максимальная длина 40.
Ловушки
- Целочисленный перебор x вместо дробного — теряются граничные эффекты.
- Путаница min/max длины и направления покрытия (пересечение против объединения).
02
Множества
«A — множество: минимум и максимум собираем поэлементно»
Признаки в условии
- заданы множества P, Q (списком или правилом), элементы — натуральные числа
- вопрос про количество или сумму элементов A
Идея (шаблон другой!)
Здесь A — не число и не отрезок, а множество, поэтому перебирать A в цикле нельзя. Истинность для каждого x зависит только от того, лежит ли этот x в A. Значит для каждого x независимо решаем: он обязан быть в A, запрещён или свободен. Минимум и максимум собираются в одном проходе.
Функция выражения + сбор A
P = set(range(2, 21, 2)) # пример: {2,4,...,20}
Q = set(range(5, 51, 5)) # пример: {5,10,...,50}
def f(A, x): # A — множество; истинность выражения для данного x
# ((x∈A) → (x∈P)) ∧ ((x∈Q) → ¬(x∈A))
return ((x in A) <= (x in P)) and ((x in Q) <= (not (x in A)))
A_max, A_min = set(), set()
for x in range(0, 1000):
can_in = f({x}, x) # выражение истинно, если x ЛЕЖИТ в A
can_out = f(set(), x) # выражение истинно, если x НЕ лежит в A
if can_in: # для МАКСИМУМА берём всё допустимое
A_max.add(x)
if not can_out: # для МИНИМУМА — только обязательное
A_min.add(x)
print(len(A_max), sum(A_max)) # наибольшее множество: размер и сумма
print(len(A_min), sum(A_min)) # наименьшее множество: размер и сумма
Аналитика для больших чисел
- перевести в язык включений:
(x∈A) → (x∈P) означает A ⊆ P; ¬(x∈Q) → ¬(x∈A) (контрапозиция) означает A ⊆ Q;
- тогда
A ⊆ P ∩ Q — для максимума берём всё пересечение, для минимума — только вынужденные элементы;
- если множества заданы правилом (кратные m, биты) — задача фактически сводится к делимости (тип 03) или битам (тип 04).
Ловушки
- Путаница
⊆ и ⊇, неверная контрапозиция.
- «Наибольшее количество» ≠ «наибольшая сумма» — смотри, что именно спрашивают.
03
Делимость (ДЕЛ)
«ДЕЛ(x, A): x кратно A»
Признаки в условии
- функция
ДЕЛ(n, m) — «n делится на m без остатка»
- вопрос про наибольшее / наименьшее натуральное A
- часто множитель-ограничитель
ДЕЛ(C, A) (A — делитель числа C)
Идея
A — одно натуральное число, функция f(A, x). Перебор A в обе стороны для минимума/максимума. x — натуральное, поэтому range(1, N), где N больше НОК всех чисел условия.
Функция выражения
def D(n, m):
return n % m == 0
def f(A, x):
# ДЕЛ(120, A) ∧ ((ДЕЛ(x,70) ∧ ДЕЛ(x,30)) → ДЕЛ(x,A))
return D(120, A) and ((D(x, 70) and D(x, 30)) <= D(x, A))
Аналитика для больших чисел
- ДЕЛ(x, A) истинно ⇔ x кратно A. Работаем с множествами кратных.
(ДЕЛ(x,m) ∧ ДЕЛ(x,k)) → ДЕЛ(x,A), наибольшее A: посылка истинна при x, кратном НОК(m, k), значит наибольшее A = НОК(m, k) (а при ограничителе ДЕЛ(C,A) — наибольший делитель C, кратный нужному).
(ДЕЛ(x,m) ∨ ДЕЛ(x,k)) → ДЕЛ(x,A): A = НОД(m, k) (пример: для 40 и 64 наибольшее A = НОД = 8).
ДЕЛ(x,A) → (ДЕЛ(x,m) ∨ ДЕЛ(x,k)), наименьшее A: каждое кратное A делится на m или k — ищем через простые множители (пример: для 19 и 15 наименьшее A = 285).
- раскладываем m, k на простые: для НОК берём
max степеней, для НОД — min; полезно НОД·НОК = m·k.
Ловушки
- Путают НОД и НОК; забывают множитель-ограничитель
ДЕЛ(C, A), который сужает A до делителей C.
- Слишком маленький диапазон x (должен превышать НОК всех чисел).
- A для делимости начинается с 1 (деление на 0 недопустимо).
05
Плоскость (x, y)
«Две переменные, метод опасной зоны и схема min/max для больших чисел»
Признаки в условии
- две переменные x и y, неравенства / произведения / линейные формы
- «при любых целых (не)отрицательных x и y»
Идея
Выражение зависит от двух переменных — функция f(A, x, y), а проверка идёт двойным перебором по x и y. Старт перебора зависит от условия: натуральные → с 1, неотрицательные → с 0.
Функция выражения и поиск минимума/максимума
def f(A, x, y):
# (x·y > A) ∨ (x > y) ∨ (11 > x)
return (x * y > A) or (x > y) or (11 > x)
ok = [A for A in range(0, 1000)
if all(f(A, x, y)
for x in range(0, 200) # неотрицательные → с 0
for y in range(0, 200))]
print(max(ok)) # наибольшее A
print(min(ok)) # наименьшее A
Аналитика для больших чисел
Каждое условие — это область на плоскости, а не только прямая:
- линейное неравенство
x + y ≤ 40 — полуплоскость (всё под/над прямой);
x·y ≥ A — область под/над гиперболой;
x² + y² ≤ R² — круг; x > A — вертикальная полуплоскость и т.д.
Выражение с ∨ истинно всюду ⇔ области-слагаемые в объединении покрывают всю плоскость. Ищем «дыру» — пересечение дополнений (где все слагаемые ложны). Обычно это ограниченная область, и её угловая (крайняя) точка даёт ответ.
Метод областей на плоскости
Пример: (x ≥ A) ∨ (y ≥ A) ∨ (x + y ≤ 40), истинно при всех натуральных x, y. Найти наибольшее A.
(x≥A) и (y≥A) закрывают верхнюю и правую полуплоскости; (x+y≤40) — нижний треугольник. Остаётся «дыра» — квадрат x, y < A. Худшая точка — угол (A−1, A−1); она обязана попасть под прямую: 2(A−1) ≤ 40 → A ≤ 21. Ответ 21.
Оптимальный перебор для больших чисел
Не перебирай 0..огромное по обеим осям — это и долго, и не влезает. Опасны только точки, где «всё остальное» ложно, а это ограниченная зона (здесь x, y < A). Перебирай именно её:
def f(A, x, y):
return (x >= A) or (y >= A) or (x + y <= 40)
ans = 0
for A in range(1, 200):
if all(f(A, x, y)
for x in range(1, A) # опасны только x < A
for y in range(1, A)): # и y < A
ans = A
print(ans) # 21
Для совсем больших границ идут дальше: для каждого x вычисляют граничный y аналитически (из уравнения области) и проверяют только критические точки границы — двойной перебор сводится к одинарному.
Опасная зона: прикрытие против спасателя
Тот же метод областей, но удобнее на словах. Делим условия на два вида:
- Прикрытие — все условия без A. Где хоть одно истинно — всё выражение истинно, и значение A не важно.
- Спасатель — условие с A. Нужен лишь там, где прикрытие отказало.
Опасная зона — точки, где всё прикрытие ложно. Задача: подобрать A так, чтобы спасатель был истинным во всей зоне. Решает крайняя (самая неудобная) точка зоны.
Спасатель с двумя координатами: схема min / max
Самый коварный случай — спасатель сравнивает A сразу с обеими координатами. Пара условий сворачивается в одно — про наибольшую координату:
(A < x) ∨ (A < y) ⟺ A < max(x, y)хотя бы одна координата больше A
(A > x) ∧ (A > y) ⟺ A > max(x, y)обе координаты меньше A
Спасатель обязан держаться во всей зоне, поэтому всё решает крайнее значение max(x,y) по зоне.
Что уменьшаем, что увеличиваем
| Спасатель |
Равносильно |
По зоне ищем |
Ответ |
(A<x) ∨ (A<y) |
A < max(x, y) |
минимум max — точка баланса x≈y |
наиб. A = min − 1 |
(A>x) ∧ (A>y) |
A > max(x, y) |
максимум max — дальняя вершина |
наим. A = max + 1 |
Одной фразой: дизъюнкция A<… → минимизируем большую координату (баланс), A на 1 меньше; конъюнкция A>… → максимизируем её (вершина), A на 1 больше.
минимумточка баланса
На прямой a·x + b·y = N (зона-линия от ≠ или граница полуплоскости) наибольшая координата минимальна при x = y:
x = y = N / (a + b)здесь max(x, y) минимален
максимумдальняя вершина
В треугольнике a·x + b·y ≤ N (зона от >) max берётся в дальней вершине — на оси:
max max(x, y) = max(N/a, N/b)бо́льший из интерсептов
Три примера с большими числами
Пример 1 — наибольшее A: (3y + 2x ≠ 500000) ∨ (A < x) ∨ (A < y), целые неотрицательные x, y.
Спасатель (A<x)∨(A<y) = A < max(x,y) → ищем минимум max. Прикрытие 3y+2x ≠ 500000 ложно на прямой 2x+3y=500000 — это зона. Баланс x=y: 5x=500000 → x=y=100000, max=100000. Нужно A < 100000 → наибольшее A = 99999
Пример 2 — наибольшее A: (y + 4x < 850000) ∨ (A < x) ∨ (A < y), целые неотрицательные x, y.
Спасатель = A < max(x,y) → минимум max. Прикрытие 4x+y < 850000 ложно при 4x+y ≥ 850000 — зона-полуплоскость; минимум max лежит на границе 4x+y=850000. Баланс: 5x=850000 → x=y=170000. Нужно A < 170000 → наибольшее A = 169999
Пример 3 — наименьшее A: (y + 3x > 900000) ∨ (A > x) ∧ (A > y), целые неотрицательные x, y.
Приоритет: ∧ сильнее ∨, значит спасатель — (A>x)∧(A>y) = A > max(x,y) → ищем максимум max. Прикрытие 3x+y > 900000 ложно при 3x+y ≤ 900000 — зона-треугольник. Дальняя вершина: интерсепты x=300000 (точка (300000;0)) и y=900000 (точка (0;900000)); большая — 900000. Нужно A > 900000 → наименьшее A = 900001
Проверка кодом (умный перебор по границе)
Перебираем не всю плоскость, а только границу зоны — один цикл, O(n):
# пример 1: зона — прямая 2x + 3y = N; спасатель A < max(x, y)
N = 500000
mn = min(max(x, (N-2*x)//3)
for x in range(0, N//2+1)
if (N-2*x) % 3 == 0) # только целые точки прямой
print(mn - 1) # 99999
Пример 2: пройти границу 4x+y=850000, взять min(max(x, 850000−4x)) → 169999. Пример 3: вершины всего две — цикл не нужен, max(300000, 900000)=900000 → 900001.
Ловушки
- Перебор с 1 при «неотрицательных» (надо с 0); слишком узкие границы перебора для произведений
x·y.
- Неверное направление неравенства при выборе min/max A.
- Приоритет:
∧ связывает сильнее ∨ — P ∨ Q ∧ R это P ∨ (Q ∧ R) (см. пример 3).
- Знак
≠ делает зону не областью, а прямой — крайнюю точку ищем по её целым точкам (баланс x=y=N/(a+b)).
- Спасатель с двумя координатами: дизъюнкция
A<… → минимум (баланс), конъюнкция A>… → максимум (вершина) — не перепутай.
06
Комбинированные
«Делимость + отрезок / неравенство в одном выражении»
Признаки в условии
- в одном выражении сочетаются
ДЕЛ и x ∈ […] или ДЕЛ и линейное неравенство с A
- вложенные импликации, иногда два параметра
Идея
Функция та же — f(A, x), просто внутри несколько проверок. Драйвер минимума/максимума не меняется.
Функция выражения
def D(n, m): return n % m == 0
def seg(L, R, x): return L <= x <= R
def f(A, x):
# ДЕЛ(x, A) ∨ ((x ∈ [60;80]) → ¬ДЕЛ(x, 22))
return D(x, A) or ((not seg(60, 80, x)) or (not D(x, 22)))
Аналитика для больших чисел
- разбить на части: посчитать «известную» часть (без A) и найти x, на которых она ложна — именно там A обязан обеспечить истинность;
- для
(ДЕЛ(x,9) ∧ ДЕЛ(x,4)) → (x + A ≥ 100): посылка истинна при x, кратном НОК(9,4)=36; наименьший такой x = 36 даёт жёсткое 36 + A ≥ 100 ⇒ A ≥ 64 — проверяем все критические x;
- комбинируем якоря: НОД/НОК (делимость) и границы (отрезки/неравенства).
Ловушки
- Упускают одно из критических x; неверно комбинируют кванторы.
- При двух параметрах перебор становится двумерным.
07
Редкие форматы
«Нестандартные формулировки 2024–2026»
Что сюда входит
- Три и более отрезка с эквивалентностями:
((x∈P)≡(x∈Q)) → ((x∈R)≡(x∈Q)) с шестизначными границами — только аналитика.
- Тождественная ЛОЖЬ вместо истины («= 0 при любом x»): инвертируем всю логику, в коде
not any(...). Часто в битовых задачах.
- Несколько параметров / два неизвестных в плоскости (A входит в несколько слагаемых) — двумерный перебор A.
- Очень большие константы в плоскости (78125, 152, 110, 128) — графический метод обязателен.
- Гибриды ДЕЛ + отрезок (с 2024 закрепились как отдельный жанр).
- Квантор «существует» вместо «для всех» — в коде
any(...) вместо all(...).
- Множества по правилу (кратные / биты), маскирующиеся под тип 02, но решаемые методами типов 03/04.
Универсальный каркас под любой редкий формат
# 1) выражение → в функцию f(A, x) или f(A, x, y)
# 2) выбрать квантор: all (для всех) или any (существует)
# 3) выбрать область x: range(1,N) натуральные / range(0,N) неотрицательные / i/2 действительные
# 4) выбрать направление A: range(BIG,0,-1) максимум / range(1,BIG) минимум
def f(A, x):
return ... # сюда логику из условия
for A in range(1, 10**6): # минимум; для максимума — реверс
if all(f(A, x) for x in range(1, 100000)):
print(A); break
Ловушки
- Для «тождественно ложно» не перепутай
all/any: ложно при любом x — это not any(f(A,x) ...).
- При больших константах сначала аналитика (область / прямая), и только проверка — кодом-подстановкой.