Логические выражения с параметром A
Дана формула с неизвестным A, и она должна быть истинна при всех x. Формулу переводим в Python, перебираем A и проверяем. Один шаблон закрывает почти все задачи.
- 1Что проверяет номер
- 2Формула в Python и общий шаблон
- 3ДЕЛ: делимость
- 4Поразрядная конъюнкция
- 5Неравенства с двумя переменными
- 6Отрезки
- 7Множества
- 8Проверяем руками
- 9Ловушки и домашка
Что проверяет номер
Дана логическая формула с неизвестным A. Это может быть число, отрезок или множество. Надо найти такое A, при котором формула истинна для всех x. Именно это значат слова «тождественно истинна».
Спрашивают наименьшее или наибольшее A. Формулы с делимостью, поразрядным И и неравенствами.
ДЕЛ(x, 128) → (¬ДЕЛ(x, A) → ¬ДЕЛ(x, 80)). Для какого наибольшего A формула истинна при любом x?
Спрашивают длину отрезка или сумму элементов множества.
P = [15; 40], Q = [30; 65]. Какова наименьшая длина отрезка A для формулы P → ((Q ∧ ¬A) → ¬P)?
Основной способ это код: перебираем A и проверяем формулу на большом диапазоне x. Руками проверяем себя в конце урока.
В первом примере A = 640, во втором длина 10. Как их получить, разберём дальше.
Формула в Python и общий шаблон
| В условии | В Python |
|---|---|
| ¬ | not |
| ∧ | and |
| ∨ | or |
| → | <= |
| ≡ | == |
Импликация записывается через <=, потому что True <= False это False, а все остальные сочетания дают True. Как раз так работает импликация: ложна она только тогда, когда из истины следует ложь.
В логике порядок действий такой: ¬, ∧, ∨, →, ≡. А в Python сравнения <= и == выполняются раньше, чем not, and и or. Поэтому каждую импликацию и эквивалентность бери в скобки вместе с обеими частями.
Вот что будет без скобок. Формула A → (B ∧ C) при A = 0 истинна, а запись без скобок даёт другое:
print(False <= True and False) # Python считает (False <= True) and False print(False <= (True and False)) # а так как надо
Общий шаблон
Описываем формулу функцией f, перебираем A и проверяем, что f истинна для всех x. Функция all(...) истинна, когда истинна каждая проверка внутри.
def d(n, m): return n % m == 0 # n делится на m def f(x, A): return d(x, 128) <= ((not d(x, A)) <= (not d(x, 80))) print(max(A for A in range(1, 1000) if all(f(x, A) for x in range(1, 2000))))
Ответ 640. Если нужно наименьшее значение, max меняем на min. Диапазон x берём с запасом: range(1, 2000) для обычных чисел, range(0, 4000) для поразрядных.
ДЕЛ: делимость
ДЕЛ(n, m) значит «n делится на m без остатка». Пишем функцию d, а дальше формулу из условия. Пример с наибольшим A был в прошлом разделе, вот пример с наименьшим:
def d(n, m): return n % m == 0 def f(x, A): return d(x, A) <= (d(x, 18) or (not d(x, 24))) print(min(A for A in range(1, 200) if all(f(x, A) for x in range(1, 2000))))
Для какого наибольшего натурального числа A формула ДЕЛ(x, 36) → (¬ДЕЛ(x, A) → ¬ДЕЛ(x, 60)) тождественно истинна?
Поразрядная конъюнкция
x & 52 это поразрядное И: единица стоит только в тех разрядах, где она есть у обоих чисел. Сравнение с нулём пишется без скобок вокруг x & 52, потому что & в Python выполняется раньше, чем != и ==.
def f(x, A): return ((x & 52 != 0) and (x & 48 == 0)) <= (not (x & A == 0)) print(min(A for A in range(1, 2000) if all(f(x, A) for x in range(0, 4000))))
В условии обычно написано x & A ≠ 0, поэтому not (x & A == 0) можно записать и как x & A != 0.
Для какого наименьшего натурального числа A формула ((x & 44 ≠ 0) ∧ (x & 12 = 0)) → (x & A ≠ 0) тождественно истинна при любом целом неотрицательном x?
Неравенства с двумя переменными
Тут внутри all два перебора: по x и по y.
def f(x, y, A): return (x + 2 * y != 58) or (A > 2 * x) or (A > y) print(min(A for A in range(1, 200) if all(f(x, y, A) for x in range(1, 500) for y in range(1, 500))))
Такой код уже работает пару секунд. Если он упирается в лимит времени, подбери диапазоны меньше, но так, чтобы опасные значения в них попадали. В примере важны только пары, где x + 2y = 58, значит x и y не больше 58.
Для какого наименьшего натурального числа A формула (x + 3y ≠ 60) ∨ (A > x) ∨ (A > y) тождественно истинна при любых натуральных x и y?
Отрезки
Тут A это отрезок [a1; a2], а спрашивают его длину. Проверять все x не нужно. Значение формулы меняется только у концов отрезков, поэтому берём опасные точки: концы отрезков из условия и точки чуть левее и правее. Концы A ищем среди них же.
def f(x): P = 15 <= x <= 40 Q = 30 <= x <= 65 A = a1 <= x <= a2 return P <= ((Q and (not A)) <= (not P)) d = [y for x in (15, 30, 40, 65) for y in (x, x - 0.1, x + 0.1)] n = [] for a1 in d: for a2 in d: if a2 >= a1 and all(f(x) for x in d): n.append(a2 - a1) print(round(min(n)))
Здесь a1 и a2 внутри f берутся из цикла снаружи. round нужен, потому что из-за 0.1 длина получается с хвостиком.
- Нужна наибольшая длина:
minменяем наmax. - Формула должна быть ложной при любом
x: проверяемf(x) == 0вместоf(x), то естьall(f(x) == 0 for x in d).
На числовой прямой даны отрезки P = [12; 50] и Q = [35; 70]. Какова наименьшая длина отрезка A, при которой формула P → ((Q ∧ ¬A) → ¬P) тождественно истинна?
Множества
Тут A это множество чисел. Начинаем с пустого и идём по всем x. Если формула ложна, значит этот x обязан быть в A, и мы его добавляем.
a = set() def f(a): P = x in {2, 4, 6, 8, 10, 12} Q = x in {4, 5, 6, 7, 8} A = x in a return (P <= (not Q)) or A for x in range(1, 100): if f(a) == 0: # формула ложна a.add(x) # значит, x обязан быть в A print(sorted(a)) print(sum(a))
Тут x внутри f тоже берётся из цикла снаружи. Если множество нужно не наименьшее, а наибольшее, стартуем с a = set(range(1, 100)) и убираем лишнее через a.remove(x).
Даны множества P = {1, 3, 5, 7, 9, 11} и Q = {3, 6, 9, 12}. Формула (x ∈ P → x ∉ Q) ∨ (x ∈ A) тождественно истинна при натуральных x от 1 до 99. Какова наименьшая сумма элементов множества A?
Проверяем руками
Код даёт ответ, а руками удобно проверить, что формула записана верно. Порядок такой:
- С частью без A находим значения
xиy. - Часть без
Aделаем ложной. - Делаем выводы и пишем ответ.
Для неравенств и ДЕЛ правило короткое: отрицаем условия и решаем.
Законы
A → B = ¬A ∨ B¬(A ∨ B) = ¬A ∧ ¬B¬(A ∧ B) = ¬A ∨ ¬B¬¬A = A
ДЕЛ руками
Разберём формулу ДЕЛ(x, 128) → (¬ДЕЛ(x, A) → ¬ДЕЛ(x, 80)). Для краткости будем писать только числа.
- Записываем:
128 → (¬A → ¬80). - Упрощаем:
¬128 ∨ A ∨ ¬80, то есть¬128 ∨ ¬80 ∨ A. - Сворачиваем обратно:
(128 ∧ 80) → A.
Значит, если x делится на 128 и на 80, то он делится на A. Такие x это числа, кратные 640, поэтому A должно быть делителем 640. Наибольшее A равно 640, как и в коде.
Отрезки и множества руками
Формула P → ((Q ∧ ¬A) → ¬P) по тем же законам равна (P ∧ Q) → A. Значит, A должен накрыть общую часть P и Q, и наименьшая длина это длина пересечения.
С множествами так же. Формула (P → ¬Q) ∨ A требует, чтобы A содержало пересечение P и Q. Напомним: объединение это всё, что есть хотя бы в одном множестве, а пересечение это общая часть.
Ловушки и домашка
| Ловушка | Как не попасться |
|---|---|
min и max перепутаны | Смотри, что просят: наименьшее или наибольшее |
| Импликация записана не так | Это <=, а не -> и не >= |
Нет скобок вокруг <= и == | В Python сравнения выполняются раньше not, and, or. Ставь скобки |
Слишком маленький диапазон x | Неверное A покажется подходящим. Бери диапазон с запасом |
| Отрезки: не те точки | Концы всех отрезков, точки x - 0.1 и x + 0.1, условие a2 >= a1, длину округляем через round |
| Формула должна быть ложной | Проверяй f(x) == 0 |
| Множества | f(a) == 0 значит «ложно», тогда x добавляем |
Как решать задачу
- Определи тип: ДЕЛ,
&, неравенства, отрезки, множества. - Перепиши формулу в Python по таблице и расставь скобки.
- Составь перебор:
minилиmax, диапазоныAиx. - Запусти. Проверь себя руками по разделу 8.
Домашка
Семь задач с настоящих экзаменов и из банка ФИПИ. Решай прямо здесь: кнопка «Решать здесь» открывает редактор, а код каждой задачи сохраняется.
В третьей задаче A начинается с нуля и нужно наибольшее значение. В четвёртой формула должна быть ложной, а длина наибольшей. В седьмой число 78125 слишком большое для двойного перебора: y выражается через x как 78125 - 4 * x, так что хватает одного цикла по x. Найди самое большое значение из x и y, и A будет на 1 больше.
Ещё задачи этого вида лежат в разделе «Задания», №15. Там же есть учебные задачи на & и множества.
Задачи «Попробуй сам» учебные, в домашке задачи с настоящих экзаменов и из банка ФИПИ. Код в блоках можно менять и запускать, он выполняется прямо в браузере.