Перейти до основного вмісту

Принцип включення-виключення

Принцип включення-виключення — це важливий комбінаторний спосіб обчислити розмір множини або ймовірність складних подій. Він пов'язує розміри окремих множин із розміром їхнього об'єднання.

Коли підходить цей алгоритм?
  • Чи треба порахувати об'єкти, що задовольняють хоча б одну (або жодну) з умов, причому умови перетинаються й пряме сумування дає переоблік?
  • Чи легко рахувати перетини умов (скільки об'єктів задовольняє фіксований набір умов одночасно), хоча об'єднання — важко?
  • Чи кількість умов nn невелика (приблизно n20n \lesssim 20), щоб перебрати всі 2n2^n підмножин? (якщо умов незалежні підрахунки без перетинів → Біноміальні коефіцієнти)

Формулювання

Словесне формулювання

Принцип включення-виключення можна сформулювати так:

Щоб обчислити розмір об'єднання кількох множин, треба підсумувати розміри цих множин окремо, потім відняти розміри всіх попарних перетинів множин, далі додати назад розмір перетинів трійок множин, відняти розмір четвірок множин, і так далі, аж до перетину всіх множин.

Формулювання мовою теорії множин

Наведене вище означення можна записати математично так:

i=1nAi=i=1nAi1i<jnAiAj+1i<j<knAiAjAk+(1)n1A1An\left| \bigcup_{i=1}^n A_i \right| = \sum_{i=1}^n|A_i| - \sum_{1\leq i<j\leq n} |A_i \cap A_j| + \sum _{1\leq i<j<k\leq n}|A_i \cap A_j \cap A_k| - \cdots + (-1)^{n-1} | A_1 \cap \cdots \cap A_n |

А у більш компактному вигляді:

i=1nAi=J{1,2,,n}(1)J1jJAj\left|\bigcup_{i=1}^n A_i \right| = \sum_{\emptyset \neq J\subseteq \{1,2,\ldots ,n\}} (-1)^{|J|-1}{\Biggl |}\bigcap_{j\in J}A_{j}{\Biggr |}

Формулювання через діаграми Венна

Нехай на діаграмі зображено три множини AA, BB та CC:

Діаграма Венна

Тоді площа їхнього об'єднання ABCA \cup B \cup C дорівнює сумі площ AA, BB та CC за вирахуванням двічі покритих площ ABA \cap B, ACA \cap C, BCB \cap C, але з додаванням площі, покритої трьома множинами ABCA \cap B \cap C:

S(ABC)=S(A)+S(B)+S(C)S(AB)S(AC)S(BC)+S(ABC)S(A \cup B \cup C) = S(A) + S(B) + S(C) - S(A \cap B) - S(A \cap C) - S(B \cap C) + S(A \cap B \cap C)

Це також можна узагальнити на об'єднання nn множин.

Формулювання мовою теорії ймовірностей

Якщо AiA_i (i=1,2...n)(i = 1,2...n) — це події, а P(Ai){\cal P}(A_i) — імовірність настання події AiA_i, то ймовірність їхнього об'єднання (тобто ймовірність того, що настане хоча б одна з подій) дорівнює:

P(i=1nAi)=i=1nP(Ai) 1i<jnP(AiAj) ++1i<j<knP(AiAjAk)+(1)n1P(A1An)\begin{align} {\cal P} \left( \bigcup_{i=1}^n A_i \right) &= \sum_{i=1}^n{\cal P}(A_i)\ - \sum_{1\leq i<j\leq n} {\cal P}(A_i \cap A_j)\ + \\ &+ \sum _{1\leq i<j<k\leq n}{\cal P}(A_i \cap A_j \cap A_k) - \cdots + (-1)^{n-1} {\cal P}( A_1 \cap \cdots \cap A_n ) \end{align}

А у більш компактному вигляді:

P(i=1nAi)=J{1,2,,n}(1)J1 P(jJAj){\cal P} \left(\bigcup_{i=1}^n A_i \right) = \sum_{\emptyset \neq J\subseteq \{1,2,\ldots ,n\}} (-1)^{|J|-1}\ {\cal P}{\Biggl (}\bigcap_{j\in J}A_{j}{\Biggr )}

Доведення

Для доведення зручно скористатися математичним формулюванням мовою теорії множин:

i=1nAi=J{1,2,,n}(1)J1jJAj\left|\bigcup_{i=1}^n A_i \right| = \sum_{\emptyset \neq J\subseteq \{1,2,\ldots ,n\}} (-1)^{|J|-1}{\Biggl |}\bigcap_{j\in J}A_{j}{\Biggr |}

Ми хочемо довести, що будь-який елемент, який міститься хоча б в одній із множин AiA_i, буде врахований у формулі рівно один раз (зауважимо, що елементи, відсутні в усіх множинах AiA_i, ніколи не враховуються у правій частині формули).

Розглянемо елемент xx, який зустрічається у k1k \geq 1 множинах AiA_i. Ми покажемо, що його враховано рівно один раз. Зауважимо, що:

  • у доданках, де J=1|J| = 1, елемент xx буде враховано + k+\ k разів;
  • у доданках, де J=2|J| = 2, елемент xx буде враховано  (k2)-\ \binom{k}{2} разів — оскільки він враховується в тих доданках, що включають дві з kk множин, які містять xx;
  • у доданках, де J=3|J| = 3, елемент xx буде враховано + (k3)+\ \binom{k}{3} разів;
  • \cdots
  • у доданках, де J=k|J| = k, елемент xx буде враховано (1)k1(kk)(-1)^{k-1}\cdot \binom{k}{k} разів;
  • у доданках, де J>k|J| \gt k, елемент xx буде враховано нуль разів;

Це приводить нас до такої суми біноміальних коефіцієнтів:

T=(k1)(k2)+(k3)+(1)i1(ki)++(1)k1(kk)T = \binom{k}{1} - \binom{k}{2} + \binom{k}{3} - \cdots + (-1)^{i-1}\cdot \binom{k}{i} + \cdots + (-1)^{k-1}\cdot \binom{k}{k}

Цей вираз дуже схожий на біноміальний розклад (1x)k(1 - x)^k:

(1x)k=(k0)(k1)x+(k2)x2(k3)x3++(1)k(kk)xk(1 - x)^k = \binom{k}{0} - \binom{k}{1} \cdot x + \binom{k}{2} \cdot x^2 - \binom{k}{3} \cdot x^3 + \cdots + (-1)^k\cdot \binom{k}{k} \cdot x^k

При x=1x = 1 вираз (1x)k(1 - x)^k дуже схожий на TT. Однак він містить додатковий доданок (k0)=1\binom{k}{0} = 1, і весь вираз помножений на 1-1. Це приводить нас до (11)k=1T(1 - 1)^k = 1 - T. Отже, T=1(11)k=1T = 1 - (1 - 1)^k = 1, що й треба було довести. Елемент враховано рівно один раз.

Узагальнення для обчислення кількості елементів рівно у rr множинах

Принцип включення-виключення можна переписати, щоб обчислити кількість елементів, присутніх у нуль множинах:

i=1nAi=m=0n(1)mX=miXAi\left|\bigcap_{i=1}^n \overline{A_i}\right|=\sum_{m=0}^n (-1)^m \sum_{|X|=m} \left|\bigcap_{i\in X} A_{i}\right|

Розглянемо його узагальнення для обчислення кількості елементів, присутніх рівно у rr множинах:

B=r[iBAij∉BAj]=m=rn(1)mr(mr)X=miXAi\left|\bigcup_{|B|=r}\left[\bigcap_{i \in B} A_i \cap \bigcap_{j \not\in B} \overline{A_j}\right]\right|=\sum_{m=r}^n (-1)^{m-r}\dbinom{m}{r} \sum_{|X|=m} \left|\bigcap_{i \in X} A_{i}\right|

Щоб довести цю формулу, розглянемо якесь конкретне BB. За базовим принципом включення-виключення про нього можна сказати, що:

iBAij∉BAj=m=rn(1)mrX=mBXiXAi\left|\bigcap_{i \in B} A_i \cap \bigcap_{j \not \in B} \overline{A_j}\right|=\sum_{m=r}^{n} (-1)^{m-r} \sum_{\substack{|X|=m \newline B \subset X}}\left|\bigcap_{i\in X} A_{i}\right|

Множини у лівій частині не перетинаються для різних BB, тому ми можемо підсумувати їх безпосередньо. Також варто зауважити, що будь-яка множина XX завжди матиме коефіцієнт (1)mr(-1)^{m-r}, якщо вона зустрічається, і вона зустрінеться рівно для (mr)\dbinom{m}{r} множин BB.

Застосування під час розв'язування задач

Принцип включення-виключення важко зрозуміти, не вивчивши його застосувань.

Спершу ми розглянемо три найпростіші задачі «на папері», що ілюструють застосування принципу, а потім перейдемо до практичніших задач, які важко розв'язати без принципу включення-виключення.

Задачі, де треба «знайти кількість способів», варті уваги, бо вони іноді приводять до поліноміальних розв'язків, а не обов'язково експоненціальних.

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

Задача: підрахувати, скільки існує перестановок чисел від 00 до 99 таких, що перший елемент більший за 11, а останній — менший за 88.

Підрахуймо кількість «поганих» перестановок, тобто таких, у яких перший елемент 1\leq 1 та/або останній 8\geq 8.

Позначимо через XX множину перестановок, у яких перший елемент 1\leq 1, а через YY — множину перестановок, у яких останній елемент 8\geq 8. Тоді кількість «поганих» перестановок за формулою включення-виключення дорівнюватиме:

XY=X+YXY|X \cup Y| = |X| + |Y| - |X \cap Y|

Після простого комбінаторного обчислення отримаємо:

29!+29!228!2 \cdot 9! + 2 \cdot 9! - 2 \cdot 2 \cdot 8!

Залишається лише відняти це число від загальної кількості 10!10!, щоб отримати кількість «хороших» перестановок.

Проста задача про послідовності з (0, 1, 2)

Задача: підрахувати, скільки існує послідовностей довжини nn, які складаються лише з чисел 0,1,20,1,2, таких, що кожне число зустрічається хоча б один раз.

Знову звернімося до оберненої задачі, тобто обчислимо кількість послідовностей, які не містять хоча б одного з чисел.

Позначимо через Ai(i=0,1,2)A_i (i = 0,1,2) множину послідовностей, у яких цифра ii не зустрічається. Формула включення-виключення для кількості «поганих» послідовностей буде такою:

A0A1A2=A0+A1+A2A0A1A0A2A1A2+A0A1A2|A_0 \cup A_1 \cup A_2| = |A_0| + |A_1| + |A_2| - |A_0 \cap A_1| - |A_0 \cap A_2| - |A_1 \cap A_2| + |A_0 \cap A_1 \cap A_2|
  • Розмір кожної AiA_i дорівнює 2n2^n, оскільки кожна послідовність може містити лише дві з цифр.
  • Розмір кожного попарного перетину AiAjA_i \cap A_j дорівнює 11, оскільки для побудови послідовності залишиться лише одна цифра.
  • Розмір перетину всіх трьох множин дорівнює 00, оскільки для побудови послідовності не залишиться жодної цифри.

Оскільки ми розв'язали обернену задачу, віднімаємо її від загальної кількості 3n3^n послідовностей:

3n(32n31+0)3^n - (3 \cdot 2^n - 3 \cdot 1 + 0)

Кількість цілочисельних сум з верхньою межею

Розглянемо таке рівняння:

x1+x2+x3+x4+x5+x6=20x_1 + x_2 + x_3 + x_4 + x_5 + x_6 = 20

де 0xi8 (i=1,2,6)0 \le x_i \le 8 ~ (i = 1,2,\ldots 6).

Задача: підрахувати кількість розв'язків рівняння.

Забудьмо на мить про обмеження на xix_i і просто підрахуймо кількість невід'ємних розв'язків цього рівняння. Це легко зробити за допомогою методу «зірочки та перегородки»: ми хочемо розбити послідовність із 2020 одиниць на 66 груп, що те саме, що розташувати 55 перегородок і 2020 зірочок:

N0=(255)N_0 = \binom{25}{5}

Тепер обчислимо кількість «поганих» розв'язків за принципом включення-виключення. «Поганими» будуть ті розв'язки, у яких один або більше xix_i більші або рівні 99.

Позначимо через Ak (k=1,26)A_k ~ (k = 1,2\ldots 6) множину розв'язків, де xk9x_k \ge 9, а всі інші xi0 (ik)x_i \ge 0 ~ (i \ne k) (вони можуть бути 9\ge 9 або ні). Щоб обчислити розмір AkA_k, зауважимо, що ми, по суті, маємо ту саму комбінаторну задачу, яку розв'язали у двох абзацах вище, але тепер 99 одиниць виключено зі слотів і вони точно належать першій групі. Отже:

Ak=(165)| A_k | = \binom{16}{5}

Аналогічно, розмір перетину двох множин AkA_k та ApA_p (для kpk \ne p) дорівнює:

AkAp=(75)\left| A_k \cap A_p \right| = \binom{7}{5}

Розмір кожного перетину трьох множин дорівнює нулю, оскільки 2020 одиниць не вистачить для трьох або більше змінних, більших або рівних 99.

Об'єднавши все це у формулу включення-виключення і враховуючи, що ми розв'язали обернену задачу, остаточно отримуємо відповідь:

(255)((61)(165)(62)(75))\binom{25}{5} - \left(\binom{6}{1} \cdot \binom{16}{5} - \binom{6}{2} \cdot \binom{7}{5}\right)

Це легко узагальнюється на dd чисел, що дають у сумі ss, з обмеженням 0xib0 \le x_i \le b:

i=0d(1)i(di)(s+d1(b+1)id1)\sum_{i=0}^d (-1)^i \binom{d}{i} \binom{s+d-1-(b+1)i}{d-1}

Як і вище, ми вважаємо біноміальні коефіцієнти з від'ємним верхнім індексом нульовими.

Зауважимо, що цю задачу можна було б розв'язати також динамічним програмуванням або твірними функціями. Відповідь за принципом включення-виключення обчислюється за O(d)O(d) часу (припускаючи, що математичні операції на кшталт біноміального коефіцієнта виконуються за сталий час), тоді як простий підхід із ДП потребував би O(ds)O(ds) часу.

Кількість взаємно простих чисел на заданому проміжку

Задача: дано два числа nn та rr; підрахувати кількість цілих чисел на проміжку [1;r][1;r], які є взаємно простими з nn (їхній найбільший спільний дільник дорівнює 11).

Розв'яжемо обернену задачу — обчислимо кількість чисел, що не є взаємно простими з nn.

Позначимо прості множники числа nn як pi(i=1k)p_i (i = 1\cdots k).

Скільки чисел на проміжку [1;r][1;r] діляться на pip_i? Відповідь на це запитання:

rpi\left\lfloor \frac{ r }{ p_i } \right\rfloor

Однак, якщо ми просто підсумуємо ці числа, деякі числа буде враховано кілька разів (ті, що мають кілька pip_i серед своїх множників). Тому необхідно скористатися принципом включення-виключення.

Ми переберемо всі 2k2^k підмножин чисел pip_i, обчислимо їхній добуток і додамо або віднімемо кількість кратних цього добутку.

Ось реалізація:

int solve (int n, int r) {
vector<int> p;
for (int i=2; i*i<=n; ++i)
if (n % i == 0) {
p.push_back (i);
while (n % i == 0)
n /= i;
}
if (n > 1)
p.push_back (n);

int sum = 0;
for (int msk=1; msk<(1<<p.size()); ++msk) {
int mult = 1,
bits = 0;
for (int i=0; i<(int)p.size(); ++i)
if (msk & (1<<i)) {
++bits;
mult *= p[i];
}

int cur = r / mult;
if (bits % 2 == 1)
sum += cur;
else
sum -= cur;
}

return r - sum;
}

Асимптотика розв'язку — O(n)O (\sqrt{n}).

Кількість цілих чисел на заданому проміжку, кратних хоча б одному із заданих чисел

Дано nn чисел aia_i і число rr. Потрібно підрахувати кількість цілих чисел на проміжку [1;r][1; r], кратних хоча б одному з aia_i.

Алгоритм розв'язання майже ідентичний до попередньої задачі — будуємо формулу включення-виключення для чисел aia_i, тобто кожен доданок у цій формулі — це кількість чисел, що діляться на задану підмножину чисел aia_i (іншими словами, що діляться на їхнє найменше спільне кратне).

Отже, ми переберемо всі 2n2^n підмножин цілих чисел aia_i за O(nlogr)O(n \log r) операцій, щоб знайти їхнє найменше спільне кратне, додаючи або віднімаючи кількість його кратних на проміжку. Асимптотика — O(2nnlogr)O (2^n\cdot n\cdot \log r).

Кількість рядків, що задовольняють заданий взірець

Розглянемо nn взірців рядків однакової довжини, що складаються лише з літер (a...za...z) або знаків питання. Також задано число kk. Рядок відповідає взірцю, якщо він має таку саму довжину, що й взірець, і на кожній позиції або відповідні символи рівні, або символ у взірці — це знак питання. Завдання — підрахувати кількість рядків, що відповідають рівно kk взірцям (перша задача) та хоча б kk взірцям (друга задача).

Спершу зауважимо, що ми легко можемо підрахувати кількість рядків, які задовольняють одразу всі задані взірці. Для цього просто «накладемо» взірці: переберемо позиції («слоти») і подивимося на позицію в усіх взірцях. Якщо всі взірці мають на цій позиції знак питання, то символ може бути будь-якою літерою від aa до zz. Інакше символ цієї позиції однозначно визначається тими взірцями, які не містять знака питання.

Навчимося тепер розв'язувати першу версію задачі: коли рядок має задовольняти рівно kk взірців.

Щоб розв'язати її, переберемо й зафіксуємо певну підмножину XX із множини взірців, що складається з kk взірців. Тоді нам треба підрахувати кількість рядків, які задовольняють цю множину взірців, і лише її, тобто не відповідають жодному іншому взірцю. Ми скористаємося принципом включення-виключення дещо інакше: підсумуємо по всіх надмножинах YY (підмножинах із вихідної множини рядків, що містять XX), і або додаємо до поточної відповіді, або віднімаємо від неї кількість рядків:

ans(X)=YX(1)Ykf(Y)ans(X) = \sum_{Y \supseteq X} (-1)^{|Y|-k} \cdot f(Y)

Де f(Y)f(Y) — це кількість рядків, що відповідають YY (принаймні YY).

(Якщо вам важко це збагнути, можете спробувати намалювати діаграми Венна.)

Якщо ми підсумуємо по всіх ans(X)ans(X), то отримаємо остаточну відповідь:

ans=X : X=kans(X)ans = \sum_{X ~ : ~ |X| = k} ans(X)

Однак асимптотика цього розв'язку — O(3kk)O(3^k \cdot k). Щоб її покращити, зауважимо, що різні обчислення ans(X)ans(X) дуже часто мають спільні множини YY.

Ми обернемо формулу включення-виключення і підсумовуватимемо по множинах YY. Тепер стає зрозуміло, що та сама множина YY буде врахована в обчисленні ans(X)ans(X) для (Yk)\binom{|Y|}{k} множин з однаковим знаком (1)Yk(-1)^{|Y| - k}.

ans=Y : Yk(1)Yk(Yk)f(Y)ans = \sum_{Y ~ : ~ |Y| \ge k} (-1)^{|Y|-k} \cdot \binom{|Y|}{k} \cdot f(Y)

Тепер наш розв'язок має асимптотику O(2kk)O(2^k \cdot k).

Тепер розв'яжемо другу версію задачі: знайти кількість рядків, що відповідають хоча б kk взірцям.

Звісно, ми можемо просто скористатися розв'язком першої версії задачі й додати відповіді для множин розміром більшим за kk. Однак можна помітити, що в цій задачі множина Y|Y| враховується у формулі для всіх множин розміром k\ge k, що містяться в YY. З огляду на це, ми можемо записати ту частину виразу, що множиться на f(Y)f(Y), як:

(1)Yk(Yk)+(1)Yk1(Yk+1)+(1)Yk2(Yk+2)++(1)YY(YY)(-1)^{|Y|-k} \cdot \binom{|Y|}{k} + (-1)^{|Y|-k-1} \cdot \binom{|Y|}{k+1} + (-1)^{|Y|-k-2} \cdot \binom{|Y|}{k+2} + \cdots + (-1)^{|Y|-|Y|} \cdot \binom{|Y|}{|Y|}

Звернувшись до Грема (Graham, Knuth, Patashnik. "Concrete mathematics" [1998] ), ми бачимо добре відому формулу для біноміальних коефіцієнтів:

k=0m(1)k(nk)=(1)m(n1m)\sum_{k=0}^m (-1)^k \cdot \binom{n}{k} = (-1)^m \cdot \binom{n-1}{m}

Застосувавши її тут, ми знаходимо, що вся сума біноміальних коефіцієнтів зводиться до:

(1)Yk(Y1Yk)(-1)^{|Y|-k} \cdot \binom{|Y|-1}{|Y|-k}

Таким чином, для цієї задачі ми також отримали розв'язок з асимптотикою O(2kk)O(2^k \cdot k):

ans=Y : Yk(1)Yk(Y1Yk)f(Y)ans = \sum_{Y ~ : ~ |Y| \ge k} (-1)^{|Y|-k} \cdot \binom{|Y|-1}{|Y|-k} \cdot f(Y)

Кількість способів дістатися з однієї клітинки до іншої

Є поле n×mn \times m, і kk його клітинок — непрохідні стіни. Робот спочатку перебуває у клітинці (1,1)(1,1) (нижня ліва). Робот може рухатися лише праворуч або вгору, і врешті він має дістатися до клітинки (n,m)(n,m), оминаючи всі перешкоди. Потрібно підрахувати кількість способів, як він може це зробити.

Припустимо, що розміри nn та mm дуже великі (скажімо, 10910^9), а число kk мале (близько 100100).

Поки що відсортуємо перешкоди за їхньою координатою xx, а у разі рівності — за координатою yy.

Також просто навчимося розв'язувати задачу без перешкод: тобто навчимося підраховувати кількість способів дістатися з однієї клітинки до іншої. По одній осі нам треба пройти xx клітинок, а по іншій — yy клітинок. З простої комбінаторики отримуємо формулу за допомогою біноміальних коефіцієнтів:

(x+yx)\binom{x+y}{x}

Тепер, щоб підрахувати кількість способів дістатися з однієї клітинки до іншої, оминаючи всі перешкоди, можна скористатися включенням-виключенням для розв'язання оберненої задачі: підрахувати кількість способів пройти дошкою, наступивши на підмножину перешкод (і відняти її від загальної кількості способів).

Перебираючи підмножину перешкод, на які ми наступимо, щоб підрахувати кількість способів зробити це, просто перемножуємо кількість усіх шляхів від початкової клітинки до першої з вибраних перешкод, від першої перешкоди до другої, і так далі, а потім додаємо або віднімаємо це число від відповіді відповідно до стандартної формули включення-виключення.

Однак це знову буде неполіноміальним за складністю O(2kk)O(2^k \cdot k).

Ось поліноміальний розв'язок:

Ми скористаємося динамічним програмуванням. Для зручності додамо (1,1)(1,1) на початок, а (n,m)(n,m) — у кінець масиву перешкод. Обчислимо числа d[i]d[i] — кількість способів дістатися від початкової точки (00-вої) до ii-тої, не наступаючи на жодну іншу перешкоду (окрім ii, звісно). Ми обчислимо це число для всіх клітинок-перешкод, а також для кінцевої.

Забудьмо на секунду про перешкоди і просто підрахуємо кількість шляхів із клітинки 00 до ii. Нам треба розглянути деякі «погані» шляхи — ті, що проходять через перешкоди, — і відняти їх від загальної кількості способів дістатися з 00 до ii.

Розглядаючи перешкоду tt між 00 та ii (0<t<i0 < t < i), на яку можна наступити, ми бачимо кількість шляхів із 00 до ii, що проходять через tt, у яких tt є першою перешкодою між стартом та ii. Ми можемо обчислити це як: d[t]d[t], помножене на кількість довільних шляхів із tt до ii. Кількість «поганих» способів можна підрахувати, підсумувавши це для всіх tt між 00 та ii.

Ми можемо обчислити d[i]d[i] за O(k)O(k) для O(k)O(k) перешкод, тож цей розв'язок має складність O(k2)O(k^2).

Кількість взаємно простих четвірок

Дано nn чисел: a1,a2,,ana_1, a_2, \ldots, a_n. Потрібно підрахувати кількість способів вибрати чотири числа так, щоб їхній спільний найбільший спільний дільник дорівнював одиниці.

Ми розв'яжемо обернену задачу — обчислимо кількість «поганих» четвірок, тобто четвірок, у яких усі числа діляться на якесь число d>1d > 1.

Ми скористаємося принципом включення-виключення, підсумовуючи по всіх можливих групах із чотирьох чисел, що діляться на дільник dd.

ans=d2(1)deg(d)1f(d)ans = \sum_{d \ge 2} (-1)^{deg(d)-1} \cdot f(d)

де deg(d)deg(d) — кількість простих чисел у розкладі числа dd на множники, а f(d)f(d) — кількість четвірок, що діляться на dd.

Щоб обчислити функцію f(d)f(d), треба лише підрахувати кількість кратних dd (як згадувалося в попередній задачі) і скористатися біноміальними коефіцієнтами, щоб підрахувати кількість способів вибрати чотири з них.

Таким чином, за формулою включення-виключення ми додаємо кількість груп із чотирьох чисел, що діляться на просте число, потім віднімаємо кількість четвірок, що діляться на добуток двох простих, додаємо четвірки, що діляться на три прості, і так далі.

Кількість гармонічних трійок

Дано число n106n \le 10^6. Потрібно підрахувати кількість трійок 2a<b<cn2 \le a < b < c \le n, які задовольняють одну з таких умов:

  • або gcd(a,b)=gcd(a,c)=gcd(b,c)=1{\rm gcd}(a,b) = {\rm gcd}(a,c) = {\rm gcd}(b,c) = 1,
  • або gcd(a,b)>1,gcd(a,c)>1,gcd(b,c)>1{\rm gcd}(a,b) > 1, {\rm gcd}(a,c) > 1, {\rm gcd}(b,c) > 1.

По-перше, одразу перейдемо до оберненої задачі — тобто підрахуємо кількість негармонічних трійок.

По-друге, зауважимо, що будь-яка негармонічна трійка складається з пари взаємно простих чисел і третього числа, яке не є взаємно простим хоча б з одним із цієї пари.

Таким чином, кількість негармонічних трійок, що містять ii, дорівнює кількості цілих чисел від 22 до nn, взаємно простих з ii, помноженій на кількість цілих чисел, не взаємно простих з ii.

Або gcd(a,b)=1gcd(a,c)>1gcd(b,c)>1gcd(a,b) = 1 \wedge gcd(a,c) > 1 \wedge gcd(b,c) > 1

або gcd(a,b)=1gcd(a,c)=1gcd(b,c)>1gcd(a,b) = 1 \wedge gcd(a,c) = 1 \wedge gcd(b,c) > 1

В обох цих випадках трійку буде враховано двічі. Перший випадок буде враховано, коли i=ai = a і коли i=bi = b. Другий випадок буде враховано, коли i=bi = b і коли i=ci = c. Тому, щоб обчислити кількість негармонічних трійок, ми підсумовуємо це обчислення по всіх ii від 22 до nn і ділимо його на 22.

Тепер залишилося лише навчитися підраховувати кількість взаємно простих з ii на проміжку [2;n][2;n]. Хоча ця задача вже згадувалася, наведений вище розв'язок тут не підходить — він вимагав би факторизації кожного з цілих чисел від 22 до nn, а потім перебору всіх підмножин цих простих чисел.

Швидший розв'язок можливий за допомогою такої модифікації решета Ератосфена:

  1. По-перше, знаходимо всі числа на проміжку [2;n][2;n] такі, що їхній простий розклад на множники не включає жоден простий множник двічі. Нам також треба знати для цих чисел, скільки множників вони містять.

    • Для цього ми вестимемо масив deg[i]deg[i] для зберігання кількості простих чисел у розкладі ii на множники, та масив good[i]good[i], щоб позначити, чи містить ii кожен множник не більше одного разу (good[i]=1good[i] = 1), чи ні (good[i]=0good[i] = 0). Перебираючи від 22 до nn, якщо ми доходимо до числа, у якого degdeg дорівнює 00, то це просте число і його degdeg дорівнює 11.
    • Під час решета Ератосфена ми перебиратимемо ii від 22 до nn. Обробляючи просте число, ми проходимо всі його кратні й збільшуємо їхні deg[]deg[]. Якщо одне з цих кратних є кратним квадрата ii, то ми можемо встановити goodgood як false.
  2. По-друге, нам треба обчислити відповідь для всіх ii від 22 до nn, тобто масив cnt[]cnt[] — кількість цілих чисел, не взаємно простих з ii.

    • Для цього згадаймо, як працює формула включення-виключення — фактично тут ми реалізуємо ту саму концепцію, але з оберненою логікою: ми перебираємо компонент (добуток простих чисел із розкладу на множники) і додаємо або віднімаємо його доданок у формулі включення-виключення для кожного з його кратних.
    • Отже, припустимо, ми обробляємо число ii таке, що good[i]=truegood[i] = true, тобто воно бере участь у формулі включення-виключення. Перебираємо всі числа, кратні ii, і або додаємо, або віднімаємо N/i\lfloor N/i \rfloor від їхнього cnt[]cnt[] (знак залежить від deg[i]deg[i]: якщо deg[i]deg[i] непарне, то ми маємо додати, інакше — відняти).

Ось реалізація:

int n;
bool good[MAXN];
int deg[MAXN], cnt[MAXN];

long long solve() {
memset (good, 1, sizeof good);
memset (deg, 0, sizeof deg);
memset (cnt, 0, sizeof cnt);

long long ans_bad = 0;
for (int i=2; i<=n; ++i) {
if (good[i]) {
if (deg[i] == 0) deg[i] = 1;
for (int j=1; i*j<=n; ++j) {
if (j > 1 && deg[i] == 1)
if (j % i == 0)
good[i*j] = false;
else
++deg[i*j];
cnt[i*j] += (n / i) * (deg[i]%2==1 ? +1 : -1);
}
}
ans_bad += (cnt[i] - 1) * 1ll * (n-1 - cnt[i]);
}

return (n-1) * 1ll * (n-2) * (n-3) / 6 - ans_bad / 2;
}

Асимптотика нашого розв'язку — O(nlogn)O(n \log n), бо майже для кожного числа до nn ми робимо n/in/i ітерацій у вкладеному циклі.

Кількість перестановок без нерухомих точок (безлади)

Доведіть, що кількість перестановок довжини nn без нерухомих точок (тобто жодне число ii не стоїть на позиції ii — таку перестановку також називають безладом) дорівнює такому числу:

n!(n1)(n1)!+(n2)(n2)!(n3)(n3)!+±(nn)(nn)!n! - \binom{n}{1} \cdot (n-1)! + \binom{n}{2} \cdot (n-2)! - \binom{n}{3} \cdot (n-3)! + \cdots \pm \binom{n}{n} \cdot (n-n)!

і приблизно дорівнює:

n!e\frac{ n! }{ e }

(якщо заокруглити цей вираз до найближчого цілого — отримаємо рівно кількість перестановок без нерухомих точок)

Позначимо через AkA_k множину перестановок довжини nn з нерухомою точкою на позиції kk (1kn1 \le k \le n) (тобто елемент kk стоїть на позиції kk).

Тепер ми скористаємося формулою включення-виключення, щоб підрахувати кількість перестановок із хоча б однією нерухомою точкою. Для цього нам треба навчитися підраховувати розміри перетину множин AiA_i, а саме:

Ap=(n1)! ,ApAq=(n2)! ,ApAqAr=(n3)! ,,\begin{align} \left| A_p \right| &= (n-1)!\ , \\ \left| A_p \cap A_q \right| &= (n-2)!\ , \\ \left| A_p \cap A_q \cap A_r \right| &= (n-3)!\ , \\ \cdots , \end{align}

бо якщо ми знаємо, що кількість нерухомих точок дорівнює xx, то нам відомі позиції xx елементів перестановки, а всі інші (nx)(n-x) елементів можна розмістити будь-де.

Підставивши це у формулу включення-виключення і враховуючи, що кількість способів вибрати підмножину розміру xx з множини nn елементів дорівнює (nx)\binom{n}{x}, ми отримуємо формулу для кількості перестановок із хоча б однією нерухомою точкою:

(n1)(n1)!(n2)(n2)!+(n3)(n3)!±(nn)(nn)!\binom{n}{1} \cdot (n-1)! - \binom{n}{2} \cdot (n-2)! + \binom{n}{3} \cdot (n-3)! - \cdots \pm \binom{n}{n} \cdot (n-n)!

Тоді кількість перестановок без нерухомих точок дорівнює:

n!(n1)(n1)!+(n2)(n2)!(n3)(n3)!+±(nn)(nn)!n! - \binom{n}{1} \cdot (n-1)! + \binom{n}{2} \cdot (n-2)! - \binom{n}{3} \cdot (n-3)! + \cdots \pm \binom{n}{n} \cdot (n-n)!

Спростивши цей вираз, ми отримуємо точний та наближений вирази для кількості перестановок без нерухомих точок:

n!(111!+12!13!+±1n!)n!en! \left( 1 - \frac{1}{1!} + \frac{1}{2!} - \frac{1}{3!} + \cdots \pm \frac{1}{n!} \right ) \approx \frac{n!}{e}

(оскільки сума в дужках — це перші n+1n+1 доданків розкладу e1e^{-1} у ряд Тейлора)

Варто зауважити, що схожу задачу можна розв'язати в такий самий спосіб: коли треба, щоб нерухомі точки не були серед mm перших елементів перестановки (а не серед усіх, як ми щойно розв'язали). Отримана формула така сама, як наведена вище точна формула, але вона йтиме до суми по kk, а не по nn.

Задачі для практики

Перелік задач, які можна розв'язати за допомогою принципу включення-виключення:

Відеоматеріали