Featured image of post Формула включений-исключений: мощный метод для правильного подсчета элементов в пересекающихся множествах

Формула включений-исключений: мощный метод для правильного подсчета элементов в пересекающихся множествах

Подробное руководство по формуле включений-исключений, важному математическому инструменту для точного подсчета элементов нескольких пересекающихся множеств без дублирования. Мы объясняем все, от базового случая с 2 множествами до общего случая с n множествами, используя примеры, доказательства и примеры применения.

1. Введение

В математике и информатике мы часто сталкиваемся с ситуациями, когда нам нужно подсчитать количество элементов, удовлетворяющих нескольким условиям. Однако, когда существует несколько условий, множества элементов, удовлетворяющих каждому условию, часто перекрываются (имеют пересечения). Простое сложение приведет к многократному подсчету элементов.

Мощный метод для точного устранения этих перекрытий и получения правильного количества элементов — это Формула включений-исключений (Принцип включений-исключений).

В этой статье мы подробно объясним формулу включений-исключений, от ее базовых концепций до обобщенных математических формул, математических доказательств и конкретных примеров применения (таких как функция Эйлера и беспорядки). Кроме того, мы представим примеры реализации в программировании, чтобы углубить ваше понимание как с теоретической, так и с практической точек зрения.

2. Основы множеств и мощности

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

  • \(A, B\) : Множества
  • \(|A|\) : Количество элементов (мощность) множества \(A\)
  • \(A \cup B\) : Объединение множества \(A\) и множества \(B\) (элементы, принадлежащие хотя бы одному из них)
  • \(A \cap B\) : Пересечение множества \(A\) и множества \(B\) (элементы, принадлежащие обоим)

То, что мы хотим найти, — это мощность объединения нескольких множеств, а именно \(|A \cup B \cup \dots|\).

3. Формула включений-исключений для 2 множеств

Рассмотрим простейший случай с двумя множествами, \(A\) и \(B\).

3.1 Формула

\[ |A \cup B| = |A| + |B| - |A \cap B| \]

3.2 Интуитивное понимание

Когда вы складываете количество элементов в множестве \(A\) (\(|A|\)) и множестве \(B\) (\(|B|\)), элементы, принадлежащие обоим множествам, то есть элементы в пересечении \(A \cap B\), прибавляются дважды. Поэтому, вычитая дважды подсчитанную часть \(|A \cap B|\) ровно один раз, вы получаете правильную мощность объединения \(|A \cup B|\).

  flowchart TD
    U["Универсальное множество U"]
    A["Множество A"]
    B["Множество B"]
    AandB["A ∩ B (Пересечение)"]
    U -->|"Содержит"| A
    U -->|"Содержит"| B
    A -->|"Перекрытие"| AandB
    B -->|"Перекрытие"| AandB

4. Формула включений-исключений для 3 множеств

Когда есть три множества, все становится немного сложнее. Рассмотрим множества \(A, B, C\).

4.1 Формула

\[ |A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |B \cap C| - |C \cap A| + |A \cap B \cap C| \]

4.2 Интуитивное понимание и доказательство

  1. Сначала сложите все индивидуальные мощности: \(|A| + |B| + |C|\)
  2. При этом пересечения любых двух множеств складываются дважды, поэтому вычтите их: \(- |A \cap B| - |B \cap C| - |C \cap A|\)
  3. Наконец, рассмотрим пересечение всех трех множеств \(A \cap B \cap C\). Оно было прибавлено 3 раза на шаге 1 и вычтено 3 раза на шаге 2, в результате чего его текущий счетчик равен \(0\). Поэтому мы прибавляем его обратно один раз в конце: \(+ |A \cap B \cap C|\)

4.3 Конкретный пример: Количество целых чисел от 1 до 100, делящихся на 2, 3 или 5

  • Универсальное множество: \(U = \{1, 2, \dots, 100\}\)
  • Множество кратных 2: \(A\)
  • Множество кратных 3: \(B\)
  • Множество кратных 5: \(C\)

Давайте найдем каждую мощность (где \(\lfloor x \rfloor\) означает округление вниз).

  • \(|A| = \lfloor 100 / 2 \rfloor = 50\)
  • \(|B| = \lfloor 100 / 3 \rfloor = 33\)
  • \(|C| = \lfloor 100 / 5 \rfloor = 20\)
  • \(|A \cap B|\) (Кратные 6) \(= \lfloor 100 / 6 \rfloor = 16\)
  • \(|B \cap C|\) (Кратные 15) \(= \lfloor 100 / 15 \rfloor = 6\)
  • \(|C \cap A|\) (Кратные 10) \(= \lfloor 100 / 10 \rfloor = 10\)
  • \(|A \cap B \cap C|\) (Кратные 30) \(= \lfloor 100 / 30 \rfloor = 3\)
\[ |A \cup B \cup C| = 50 + 33 + 20 - 16 - 6 - 10 + 3 = 74 \]

Таким образом, существует 74 числа, делящихся на 2, 3 или 5.

5. Общая формула включений-исключений для \(n\) множеств

Обобщение этого на \(n\) множеств \(A_1, A_2, \dots, A_n\) дает следующую красивую формулу.

5.1 Формула

\[ \left| \bigcup_{i=1}^n A_i \right| = \sum_{k=1}^n (-1)^{k-1} \left( \sum_{1 \le i_1 < i_2 < \dots < i_k \le n} \left| A_{i_1} \cap A_{i_2} \cap \dots \cap A_{i_k} \right| \right) \]

На словах операция повторяет «прибавление мощностей пересечений нечетного количества множеств и вычитание мощностей пересечений четного количества множеств».

5.2 Краткое изложение математического доказательства

Мы покажем, что любой элемент \(x \in \bigcup_{i=1}^n A_i\) учитывается ровно один раз в вычислениях в правой части.

Предположим, некоторый элемент \(x\) содержится ровно в \(m\) множествах (\(1 \le m \le n\)). То, сколько раз \(x\) подсчитывается в правой части, можно выразить с помощью биномиальных коэффициентов следующим образом:

\[ \text{Количество раз} = \binom{m}{1} - \binom{m}{2} + \binom{m}{3} - \dots + (-1)^{m-1} \binom{m}{m} \]

По биному Ньютона известно, что \((1 - 1)^m = \binom{m}{0} - \binom{m}{1} + \binom{m}{2} - \dots + (-1)^m \binom{m}{m} = 0\). Преобразуя это:

\[ \binom{m}{0} - \left( \binom{m}{1} - \binom{m}{2} + \dots + (-1)^{m-1} \binom{m}{m} \right) = 0 \]

Поскольку \(\binom{m}{0} = 1\), выражение в скобках (которое и есть количество раз, когда учитывается \(x\)) равно ровно \(1\). Это доказывает, что каждый элемент учитывается ровно один раз без дублирования.

6. Пример применения 1: Функция Эйлера

Функция Эйлера \(\varphi(N)\) представляет количество целых чисел от \(1\) до \(N\), взаимно простых с \(N\). Это также можно вычислить с помощью формулы включений-исключений.

Пусть простые множители числа \(N\) равны \(p_1, p_2, \dots, p_k\). Пусть универсальное множество \(U = \{1, 2, \dots, N\}\), а \(A_i\) — «множество кратных \(p_i\)». То, что мы хотим найти, — это количество элементов, не принадлежащих ни одному \(A_i\).

\[ \varphi(N) = N - \left| \bigcup_{i=1}^k A_i \right| \]

Применение формулы включений-исключений и упрощение приводит к этой знаменитой формуле:

\[ \varphi(N) = N \left(1 - \frac{1}{p_1}\right) \left(1 - \frac{1}{p_2}\right) \dots \left(1 - \frac{1}{p_k}\right) \]

7. Пример применения 2: Беспорядки

Беспорядок — это перестановка чисел от \(1\) до \(n\), такая, что ни одно \(i\)-е число не находится на \(i\)-й позиции. Например, это эквивалентно общему количеству способов распределить подарки при обмене подарками так, чтобы никто не получил свой собственный подарок.

Пусть \(A_i\) — «множество перестановок, где \(i\) находится на \(i\)-й позиции». Мощность универсального множества равна \(n!\). Мы хотим найти \(n! - |A_1 \cup A_2 \cup \dots \cup A_n|\).

Мощность пересечения любых \(k\) множеств равна \((n-k)!\), и есть \(\binom{n}{k}\) способов выбрать такие \(k\) множеств. Применяя формулу включений-исключений, количество беспорядков \(D_n\) вычисляется следующим образом:

\[ D_n = n! \sum_{k=0}^n \frac{(-1)^k}{k!} \]

8. Вычисление и реализация с помощью программирования

Формула включений-исключений чрезвычайно полезна в программировании. Особенно в сочетании с побитовым полным перебором, принцип для \(n\) условий может быть реализован лаконично.

Ниже приведен код Python для нахождения «количества целых чисел от 1 до \(M\), которые делятся на любое из простых чисел в заданном списке».

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def count_multiples(M: int, primes: list[int]) -> int:
    n = len(primes)
    total_count = 0
    
    # Перебор всех подмножеств с использованием битовых масок от 1 до 2^n - 1
    for i in range(1, 1 << n):
        lcm = 1
        set_bits = 0
        
        # Вычисление произведения (НОК) выбранных простых чисел
        for j in range(n):
            if (i >> j) & 1:
                lcm *= primes[j]
                set_bits += 1
                
        # Прибавляем, если выбрано нечетное количество простых чисел, вычитаем, если четное (Формула включений-исключений)
        if set_bits % 2 == 1:
            total_count += M // lcm
        else:
            total_count -= M // lcm
            
    return total_count

# Пример выполнения
M = 100
primes = [2, 3, 5]
# Ожидаемый вывод: 74
print(f"Результат: {count_multiples(M, primes)}")

Временная сложность этого алгоритма составляет \(O(n \cdot 2^n)\), что работает достаточно быстро, если \(n\) составляет примерно до 20.

9. Заключение

Формула включений-исключений — это волшебная математическая формула, которая разбивает на первый взгляд сложные перекрытия множеств на простое и механическое повторение сложения и вычитания.

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

comments powered by Disqus