Elemente de Combinatorica 2.0

autor: Bogdan Iordache

Inainte de a parcurge acest material va recomand sa consultati articolul introductiv de aici.

Invers Modular

Incepem cu cateva notatii utile. Fie a a si b b doua numere intregi, iar m m un numar natural nenul. Folosim notatia a b   ( m o d   m ) a \equiv b\ (mod\ m) cu semnificatia ca restul impartirii numarului a a la m m este egal cu restul impartirii numarului b b la m m .

Pentru un numar a a intreg si m m natural nenul, definim inversul modular al lui a a in raport cu m m , notat cu a 1 a^{-1} , ca fiind un numar natural din invervalul [ 1 , m 1 ] [1, m-1] cu proprietatea ca: a a 1 1   ( m o d   m ) a \cdot a^{-1} \equiv 1\ (mod\ m) .

Determinarea inversului modular este utila in momentul in care vrem sa determinam restul impartirii la m m al unei formule care implica operatii de impartire. Spre exemplu, fie a a si b b doua numere intregi, cu proprietatea ca b a b | a . Presupunem ca a a' si b b' sunt resturile impartirii lui a a , respectiv b b la m m . Cunoscand a a' si b b' vrem sa determinam restul impartirii numarului a b \frac{a}{b} la m m (il vom nota cu r r ). Aceasta problema o putem rezolva astfel:

a b r   ( m o d   m )    a r b   ( m o d   m )     \frac{a}{b} \equiv r\ (mod\ m) \implies a \equiv r \cdot b\ (mod\ m) \implies
    a b 1 r b b 1   ( m o d   m )     a b 1 r   ( m o d   m ) \implies a \cdot b^{-1} \equiv r \cdot b \cdot b^{-1}\ (mod\ m) \implies a' \cdot b'^{-1} \equiv r\ (mod\ m) .

Tot ce trebuie sa facem este sa inmultim restul lui a a ( a a' ) cu inversul modular al lui b b (care este usor de vazut ca este si inversul modular al lui b b' ).

Obs. Nu intotdeauna inversul modular exista. De exemplu, care este inversul modular al lui 2 2 in raport cu 4 4 ? Nu exista niciun numar pe care l-as putea inmulti cu 2 2 astfel incat sa obtin un multiplu de 4 4 plus 1 1 . O conditie necesara ca un numar a a sa accepte invers modular in raport cu m m este ca ( a , m ) = 1 (a, m) = 1 (sa fie prime intre ele). Dem: Presupunem ca a a accepta invers modular, notat cu a 1 a^{-1} , notam cu d = ( a , m ) d = (a, m) . Avem ca d a d|a      \implies d a a 1 d|a \cdot a^{-1}      \implies d k m + 1 d|k \cdot m + 1 (divide un multiplu de m m plus 1 1 ). Dar d m d|m , obtinem prin scaderea ultimelor doua relatii ca d 1 d|1 , deci singura optiune este ( a , m ) = 1 (a, m) = 1 .

Conditia demonstrata mai devreme este necesara ( a a si m m trebuie sa fie prime intre ele pentru a gasi invers modular), dar este oare si suficienta (daca a a si m m sunt prime intre ele, avem invers modular pentru a a )? Raspunsul este da, si reiese usor din Teorema lui Euler:
a ϕ ( m ) 1   ( m o d   m ) a^{\phi(m)} \equiv 1\ (mod\ m) daca ( a , m ) = 1 (a, m) = 1 ; unde ϕ ( m ) \phi(m) este “indicatorul lui Euler” definit ca numarul de numere naturale mai mici decat m m care sunt prime cu m m .

Rescriind formula de mai sus putem extrage o formula pentru a 1 a^{-1} , anume:
a 1 a ϕ ( m ) 1   ( m o d   m ) a^{-1} \equiv a^{\phi(m) - 1}\ (mod\ m) .

Obs. daca m m este prim, din moment ce ϕ ( m ) = m 1 \phi(m) = m-1 , Teorema lui Euler ne da aceeasi relatie ca Mica Teorema a lui Fermat: a m 1 1   ( m o d   m ) a^{m-1}\equiv 1\ (mod\ m) , oricare ar fi m m prim si a a numar natural nedivizibil cu m m .

Cum calculam ϕ ( m ) \phi(m) ?

Fie p 1 t 1 p 2 t 2 p k t k p_1^{t_1} \cdot p_2^{t_2} \cdot \ldots \cdot p_k^{t_k} descompunerea in factori primi a lui m m . Indicatorul lui Euler poate fi calculat astfel:
ϕ ( m ) = m ( 1 1 p 1 ) ( 1 1 p 2 ) ( 1 1 p k ) \phi(m) = m(1 - \frac{1}{p_1})(1 - \frac{1}{p_2})\ldots(1 - \frac{1}{p_k}) .

Pentru un m m oarecare putem determina in O ( m ) O(\sqrt{m}) descompunerea in factori primi a acestuia si sa calculam indicatorul cu formula de mai sus. Daca vrem sa aflam indicatorul pentru mai multe numere, de exemplu pentru toate numerele naturale mai mici sau egale cu N N , putem apela la o metoda de tip ciur:

for (int i = 1; i <= N; ++i)
	phi[i] = i;
for (int i = 2; i <= N; ++i) {
	if (phi[i] == i) {  \\ phi[i] nu a fost modificat, i este prim
		for (int j = i; j <= N; j += i)
			phi[j] = phi[j] / i * (i - 1);
	}
}

Cum calculam a 1 a^{-1} ?

Pentru a calcula a 1 a^{-1} avem de determinat restul impartirii lui a ϕ ( m ) 1 a^{\phi(m) - 1} la m m . Acest lucru poate fi facut usor folosind exponentiere in timp logaritmic (complexitate O ( l o g   m ) ) O(log\ m)) :

int log_pow(int a, int n, int mod) {
	// calculeaza a^n % mod
	int res = 1;
	while (n) {  // scriem n in baza 2
		if (n % 2 == 1)  // daca bitul curent este 1
			res = (res * a) % mod;  // inmultim la rezultat puterea de forma a^(2^k)
		n /= 2;
		a = (a * a) % mod;  // iteram prin a, a^2, a^4, a^8, ...
	}
	return res;
}

Daca cunoastem phi_m, indicatorul lui Euler pentru m m , implementarea inversului modular se reduce la:

int inv_mod(int a, int m, int phi_m) {
	return log_pow(a, phi_m - 1, m);
}

Calculul formulelor combinatorice

Am vazut in articolul anterior cum calculul formulelor pentru combinari, aranjamente, etc. are ca principala dificultate evitarea impartirilor de factoriale. Putem acum sa ne folosim de notiunea de invers modular. Mai intai precalculam toate factorialele de care am putea avea nevoie:

fact[0] = 1;
for (int i = 1; i <= N; ++i)
	fact[i] = (i * fact[i - 1]) % MOD;

Putem calcula acum inversele modulare ale acestor factoriale. Putem eficientiza procesul folosindu-ne de faptul ca ( n 1 ) ! 1 n n ! 1   ( m o d   M O D ) (n-1)!^{-1} \equiv n \cdot n!^{-1}\ (mod\ MOD) :

inv_fact[N] = inv_mod(fact[N], MOD, phi_MOD);
for (int i = N - 1; i; --i)
	inv_fact[i] = (i + 1) * inv_fact[i + 1] % MOD;

Putem acum, spre exemplu, sa calculam C i j C_i^j astfel:

int comb_i_j = fact[i] * inv_fact[j] * inv_fact[i - j] % MOD;

Obs. Pentru a putea calcula aceste inverse modulare trebuie ca M O D MOD sa fie prim cu toate factorialele precalculate. Deobicei, in probleme, M O D MOD este un numar prim > N > N , ceea ce garanteaza aceasta restrictie. Daca nu este valabila aceasta conditie, se pot face diverse artificii pentru a precalcula factorialele ignorand factorii primi din descompunerea acestora care il divid pe M O D MOD , si calcularea separata a exponentilor acestora, puteti gasi o interpretare a acestei idei aici.

Problema 1 (Nozero)

Observația principală care ne duce la rezolvarea problemei este că numărul K este mic în comparație cu numărul total de permutări de ordin N N ( N ! N! ). De aceea pentru orice N 13 N \geq 13 și orice K 1 0 9 K \leq 10^9 , primele N 13 N-13 poziții vor fi fixate (avem valoarea egală cu poziția) și doar ultimele cel mult 13 13 valori vor fi permutate.

Astfel ajungem la următoarele subprobleme:

Subproblema 1: determinam a K K -a permutare în ordine lexicografică de dimensiune cel mult 13 13 (notăm această dimensiune cu M M ). Această subproblemă se poate rezolva în mai multe moduri întrucât lungimea permutărilor este mică. O variantă ar fi să încercăm să fixăm pe rând de la stânga la dreapta valorile. Pentru poziția i i încercăm în ordine crescătoare toate valorile care nu au fost puse încă, dacă o fixăm pe aceasta știm că elementele din dreapta ei pot fi permutate în ( M i ) ! (M-i)! moduri. Dacă numărul de moduri în care mai putem permuta ultimele M i M-i valori este mai mic decât K K , scădem din K K acest număr și încercăm o valoare mai mare pe poziția i i . La final vom avea toate valorile setate, iar K = 0.

Subproblema 2: determinarea numărului de valori care conțin cifra 0 0 și sunt mai mici sau egale decât un P dat. Deoarce știm că primele aproximativ N 13 N-13 valori (al căror număr îl vom nota cu P P ) sunt egale cu poziția lor din permutare, este suficient să număram câte dintre aceste valori conțin 0 0 . Pentru un număr de cifre c c fixat avem 9 c 9^c valori de c c cifre care nu conțin cifra 0 0 . Cu această relație numărăm toate valorile care au numărul de cifre strict mai mic decât numărul de cifre ale lui P P .
Mai avem de numărat valorile care au același număr de cifre cu P P si nu conțin 0 0 . Fiind mai mici decât P P și având același număr de cifre, putem grupa aceste valori după lungimea celui mai lung prefix pe care îl au în comun cu P P . Dacă acest prefix conține 0 nu avem ce număra, iar dacă nu, vedem câte cifre nenule mai mici strict decât cifra de pe poziția imediat următoare prefixului din P P există, iar pentru fiecare din aceste variante celelalte cifre pot fi fixate cu oricare dintre cele 9 9 valori nenule posibile.

Din cele două subprobleme putem determina câte poziții sunt valide (poziția nu conține cifra 0 0 si valoarea de la acea poziție nu conține 0 0 ).

Teorema lui Lucas

Fie P P un numar prim. Vrem sa calculam C N M   %   P C_N^M\ \%\ P (unde N M N \geq M ). Observati ca nu am dat nicio restrictie suplimentara pentru N N si M M , deci aceste valori pot fi mai mari decat P P . Ne lovim deci de problema enuntata mai devreme, in care nu putem calcula direct inversele modulare ale factorialelor, intrucat acestea pot fi divizibile cu P P .

Teorema lui Lucas ne vine in ajutor. Mai intai scriem numerele N N si M M in baza P P :
N = n k P k + n k 1 P k 1 + + n 1 P 1 + n 0 N = n_k\cdot{P^k} + n_{k-1}\cdot{P^{k-1}} + \ldots + n_1\cdot{P^1} + n_0
M = m k P k + m k 1 P k 1 + + m 1 P 1 + m 0 M = m_k\cdot{P^k} + m_{k-1}\cdot{P^{k-1}} + \ldots + m_1\cdot{P^1} + m_0
n k > 0 n_k > 0 ; 0 n i , m i < P 0 \leq n_i, m_i < P
Conform teoremei avem:
C N M i = 1 k C n i m i   ( m o d   P ) C_N^M \equiv \prod_{i=1}^k C_{n_i}^{m_i}\ (mod\ P)
cu conventia ca C n i m i = 0 C_{n_i}^{m_i} = 0 , daca n i < m i n_i < m_i .

C n i m i C_{n_i}^{m_i} poate fi calculat usor, intrucat formula sa depinde de factoriale < P ! < P! , care sunt deci prime cu P P .

Problema 2 (Jap2)

Aceasta problema se poate rezolva usor folosind direct Teorema lui Lucas.
Pentru o alta varianta de rezolvare, care se poate generaliza si la calculul de aranjamente, puteti consulta descrierea oficiala.

Problema 3 (Nmult)

Plecam de la faptul ca x i + 1 x i > w 1 x_{i+1} - x_i > w - 1 .
Realizam urmatoarea “schimbare de variabila”: y i = x i ( i 1 ) ( w 1 ) y_i = x_i - (i - 1)(w - 1) .
y i + 1 y i = x i + 1 x i ( w 1 ) > 0 y_{i+1} - y_i = x_{i+1} - x_i - (w - 1) > 0
Avem deci o bijectie (corespondenta una-la-unu) intre sirurile corecte x 1 , , x k x_1, \ldots, x_k si sirurile y 1 , , y k y_1, \ldots, y_k , cu 1 y 1 < y 2 < < y k n ( k 1 ) ( w 1 ) 1 \leq y_1 < y_2 < \ldots < y_k \leq n - (k-1)(w-1) .

Am redus problema la a determina “cate siruri strict crescatoare de k k numere naturale din intervalul [ 1 , n ( k 1 ) ( w 1 ) ] [1, n - (k-1)(w-1)] exista”. R: C n ( k 1 ) ( w 1 ) k C_{n-(k-1)(w-1)}^{k} .

Intrucat aceste combinari trebuie calculate modulo 666013 666013 (numar prim), iar n , k , w 1 0 6 n, k, w \leq 10^6 , trebuie sa folosim teorema lui Lucas pentru a calcula combinarea.

Numere Catalan

Numerele catalan se noteaza cu C n C_n si se calculeaza dupa formula C n = 1 n + 1 C 2 n n C_n = \frac{1}{n+1} C_{2n}^n .

Acestor numere le este asociata o multime variata de clase de probleme care se reduc la calcularea formulei specificate. Enumeram doar cateva dintre acestea.

a. Numarul de siruri corecte de paranteze

Consideram un sir de 2 n 2n caractere, in care n n caractere sunt ‘ ( ( ’, iar celelalte sunt ‘ ) ) ’. O parantezare corecta P P este un astfel de sir care respecta urmatoarea definitie recursiva:

Exemplu: ( ( ) ) ( ) (())() , ( ( ( ) ) ) ((())) , ( ) ( ) ( ) ()()() sunt parantezari corecte, in timp ce ) ( ( ) ) ( )(())( , ( ( ) ) ) (())) nu sunt.

Numarul de parantezari corecte de lungime 2 n 2n este C n C_n .

b. Numarul de drumuri monotone in spatiu laticeal care nu depasesc diagonala principala

Consideram un spatiu laticeal (craoiaj) de dimensiune n × n n \times n . Pornim din punctul ( 0 , 0 ) (0, 0) si dorim sa ajungem in ( n , n ) (n, n) facand pasi de lungime 1 1 unitate fie in sus, fie la dreapta, cu conditia ca niciodata sa nu depasim diagonala principala, adica sa nu ajungem intr-un punct ( i , j ) (i, j) cu i < j i < j . Cate astfel de drumuri se pot forma? R: C n C_n .

Avem mai jos toate drumurile posibile pentru n = 4 n=4 :
enter image description here

c. Numarul de arbori binari stricti

Un arbore binar strict este un arbore in care toate nodurile interne (care nu sunt frunze) au exact 2 2 fii. Pentru un arbore binar strict cu n n noduri interne vom avea mereu n + 1 n+1 frunze. Numarul de arbori binari stricti cu n n noduri interne este C n C_n .

Pentru n = 3 n=3 avem urmatorii arbori:
enter image description here

d. Numarul de triangulari ale unui poligon convex

O triangulare a unui poligon convex reprezinta o modalitate de a trasa diagonale ale acestuia care nu se intersecteaza (cu exceptia capetelor) cu scopul de a imparti suprafata acestui poligon in triunghiuri. Pentru un poligon convex cu n + 2 n+2 laturi avem C n C_n triangulari.

Triangularile pentru un hexagon sunt urmatoarele:
enter image description here

Demonstratia formulei

Putem demonstra pentru oricare dintre problemele de mai sus ca numarul de posibilitati este C n C_n , apoi sa demonstram ca aceste probleme sunt echivalente intre ele. Vom schita pe scurt demonstratia ca numarul de drumuri sus-dreapta, care nu depasesc diagonala principala intr-un caroiaj de n × n n \times n este C n C_n . Pentru alte demonstratii puteti consulta articolul de pe Wikipedia.

Putem porni de la a numara toate drumurile sus-dreapta de la ( 0 , 0 ) (0, 0) la ( n , n ) (n, n) . Acestea sunt in total C 2 n n C_{2n}^{n} (orice astfel de drum trebuie sa contina n n pasi in sus si n n pasi la dreapta, interclasati in orice mod posibil).

Trebuie sa scadem acum drumurile care depasesc diagonala principala. Pentru a le numara pe acestea folosim urmatoarea metoda: fie un astfel de drum “gresit”, consideram primul punct de pe drum de forma ( i , j ) (i, j) cu i < j i < j (prima oara cand drumul depaseste diagonala principala). Numim diagonala critica, diagonala paralela cu cea principala aflata cu o unitate deasupra acesteia, evident ( i , j ) (i, j) se afla pe diagonala critica. Aplicam o reflexie a sufixului drumului incepand de la ( i , j ) (i, j) fata de diagonala critica. Obtinem astfel, in final, un drum de la ( 0 , 0 ) (0, 0) la ( n 1 , n + 1 ) (n-1, n+1) .

Exemplu de reflexie:
enter image description here

Este usor de vazut ca avem o bijectie de la drumurile “gresite” catre toate drumurile de la ( 0 , 0 ) (0, 0) la ( n 1 , n + 1 ) (n-1, n+1) . Un drum oarecare de la ( 0 , 0 ) (0, 0) la ( n 1 , n + 1 ) (n-1, n+1) va trece cu siguranta peste diagonala principala si aplicand din nou operatia de reflexie ajungem la drumul “gresit” corespunzator. Obtinem astfel ca avem C 2 n n 1 C_{2n}^{n-1} drumuri “gresite”.

In final, C n = C 2 n n C 2 n n 1 = 1 n + 1 C 2 n n C_n = C_{2n}^n - C_{2n}^{n-1} = \frac{1}{n+1} C_{2n}^n .

In continuare, vom da cateva exemple de demonstratii de echivalenta:

i) drumuri sus-dreapta sub diagonala principala \Leftrightarrow siruri corecte de paranteze

Pornim de la urmatoarea observatie, un sir de paranteze este corect daca si numai daca:

Putem construi acum urmatoarea bijectie: pentru un drum, marcam toti pasii la dreapta cu ( ( si toti pasii in sus cu ) ) . Intrucat drumul nu depaseste diagonala principala, pentru niciun prefix nu vom avea mai multe drumuri in sus decat la dreapta, deci orice sir de paranteze astfel obtinut este corect.

ii) siruri corecte de paranteze \Leftrightarrow arbori binari stricti

Intr-un arbore binar strict, odata fixata configuratia nodurilor interne, pozitia frunzelor este unic determinata. Putem realiza o bijectie intre parantezari si arbori astfel:

Folosind procedeul de mai sus obtinem configuratia nodurilor interne, ramane doar sa mai adaugam si frunzele (un singur mod posibil). Pentru arborii din figura de mai sus, parantezarile asociate ar fi, in ordine:
( ( ( ) ) ) , ( ( ) ( ) ) , ( ( ) ) ( ) , ( ) ( ( ) ) , ( ) ( ) ( ) ((())), (()()), (())(), ()(()), ()()()

Problema 4 (Catalan)

Simpla implementare a formulei numerelor Catalan.

Problema 5 (Puteri3)

Reamintim binomul lui Newton:
( x + y ) n = k = 0 n C n k x n k y k (x+y)^n = \sum_{k=0}^n C_n^k \cdot x^{n-k} \cdot y^k

Folosim urmatoarea notatie mai generala: S ( k , n ) = i = 1 n i k S(k, n) = \sum\limits_{i=1}^n i^k .
S ( k , n ) = i = 1 n + 1 ( i 1 ) k = n k + i = 1 n ( i 1 ) k S(k, n) = \sum_{i=1}^{n+1} (i-1)^k = n^k + \sum_{i=1}^{n} (i-1)^k
S ( k , n ) = n k + i = 1 n j = 0 k C k j i j ( 1 ) k j S(k, n) = n^k + \sum_{i=1}^{n} \sum_{j=0}^{k} C_k^j \cdot i^j \cdot (-1)^{k-j}
S ( k , n ) = n k + j = 0 k C k j ( 1 ) k j S ( j , n ) S(k, n) = n^k + \sum_{j=0}^{k} C_k^j \cdot (-1)^{k-j} \cdot S(j, n)
S ( k , n ) = n k + S ( k , n ) + j = 0 k 1 C k j ( 1 ) k j S ( j , n ) S(k, n) = n^k + S(k, n) + \sum_{j=0}^{k-1} C_k^j \cdot (-1)^{k-j} \cdot S(j, n)
n k = j = 0 k 1 C k j ( 1 ) k j S ( j , n ) n^k = -\sum_{j=0}^{k-1} C_k^j \cdot (-1)^{k-j} \cdot S(j, n)
Substituim k k cu k + 1 k+1 :
n k + 1 = j = 0 k C k + 1 j ( 1 ) k j S ( j , n ) n^{k+1} = \sum_{j=0}^{k} C_{k+1}^j \cdot (-1)^{k-j} \cdot S(j, n)
n k + 1 = ( k + 1 ) S ( k , n ) + j = 0 k 1 C k + 1 j ( 1 ) k j S ( j , n ) n^{k+1} = (k+1) \cdot S(k, n) + \sum_{j=0}^{k-1} C_{k+1}^j \cdot (-1)^{k-j} \cdot S(j, n)
Obtinem formula pentru S ( k , n ) S(k, n) :
S ( k , n ) = 1 k + 1 [ n k + 1 j = 0 k 1 C k + 1 j ( 1 ) k j S ( j , n ) ] S(k, n) = \frac{1}{k+1} [n^{k+1} - \sum_{j=0}^{k-1} C_{k+1}^j \cdot (-1)^{k-j} \cdot S(j, n)]

Am obtinut deci o recurenta pentru S ( k , n ) S(k, n) bazata pe S ( 0 , n ) , S ( 1 , n ) , , S ( k 1 , n ) S(0, n), S(1, n), \ldots, S(k-1, n) . Tinand cont ca S ( 0 , n ) = n S(0, n) = n , putem determina S ( k , n ) S(k, n) in O ( k 2 ) O(k^2) .

Problema 6 (Shgraf)

Definim S [ i ] S[i] numarul de shgrafuri cu i i noduri, etichetate folosind i i etichete distincte. Un shgraf poate avea mai multe componente conexe, a caror ordine nu conteaza. Una dintre aceste componente conexe va contine nodul cu cea mai mare eticheta. Putem fixa j j dimensiunea acestei componente. Restul etichetelor din aceasta componenta pot fi alese in C i 1 j 1 C_{i-1}^{j-1} moduri. Obtinem recurenta:
S [ i ] = j = 1 i C i 1 j 1 D [ j ] S [ i j ] S[i] = \sum_{j=1}^i C_{i-1}^{j-1} \cdot D[j] \cdot S[i - j]

Am notat cu D [ j ] D[j] numarul de shgrafuri conexe cu j j noduri, etichetate folosind j j etichete distincte. Pentru a numara aceste shgrafuri observam mai intai ca structura lor corespunde unui ciclu de care sunt “agatati” arbori cu radacina in nodurile ciclului. Pentru D [ i ] D[i] , numarul de astfel de grafuri cu i i noduri, putem fixa mai intai structura ciclului. Putem fixa j j dimensiunea acestuia, avem la dispozitie ( j 1 ) ! C i j (j-1)! \cdot C_i^j moduri de a eticheta acest ciclu (alegem j j etichete si le permutam pe un ciclu de lungime j j ). Obtinem recurenta:
D [ i ] = j = 3 i ( j 1 ) ! C i j A [ j ] [ i j ] D[i] = \sum_{j=3}^{i} (j-1)! \cdot C_i^j \cdot A[j][i - j]

Am notat cu A [ i ] [ j ] A[i][j] numarul de moduri in care putem organiza j j noduri in arborii “agatati” de un ciclu cu i i noduri, etichetandu-le cu j j etichete distincte. Ciclul de i i noduri este deja fixat si etichetat, deci putem stabili o ordine a nodurilor de pe ciclu. Incercam sa fixam acum cate noduri vor fi agatate intr-un arbore cu radacina in ultimul nod de pe ciclu. Fie k k numarul acestora, putem sa le etichetam in C j k C_j^k moduri. Ramane acum sa determinam cati arbori etichetati cu k + 1 k+1 noduri exista ( k k nodurile alese, plus ultimul nod de pe ciclu). Numarul acestor arbori este ( k + 1 ) k 1 (k+1)^{k-1} (pentru demonstratie studiati Codurile Prüfer). Obtinem recurenta:
A [ i ] [ j ] = k = 0 j C j k ( k + 1 ) k 1 A [ i 1 ] [ j k ] A[i][j] = \sum_{k=0}^{j} C_j^k \cdot (k+1)^{k-1}\cdot A[i-1][j-k]

Problema ne cere sa ignoram acele shgrafuri care au cicluri de lungime mai mica decat K K . Putem “repara” recurenta pentru D [ i ] D[i] considerand doar j K j \geq K . Obtinem complexitatea finala O ( N 3 ) O(N^3) .

Problema 7 (provocare)

Pornim de la urmatoarea observatie: putem asocia fiecarui nod din arbore un sir de caractere de forma “aabbab” care descrie secventa de muchii de la radacina arborelui pana la acel nod. Evident, pentru oricare doua noduri distincte din arbore, sirurile de caractere asociate sunt diferite.

Vom incerca sa cautam binar inaltimea arborelui. Pentru o inaltime fixata numaram cate secvente de caractere corespund unei lungimi mai mici decat aceasta inaltime. Lungimea se calculeaza ca x A + y B x \cdot A + y \cdot B (unde x x si y y sunt numerele de caractere “a” si “b” din secventa, A A si B B au semnificatia din enunt). Daca numarul de astfel de secvente este mai mic decat N N , inseamna cu certitudine ca inaltimea arborelui trebuie sa fie mai mare (“nu incap toate nodurile in aceasta inaltime”), daca numarul este N \geq N vom incerca o inaltime mai mica.

Stiind ca avem x x caractere “a” si y y caractere “b”, putem genera C x + y x C_{x+y}^x secvente. Numarul pe care incercam sa il determinam, pentru o inaltime fixata ( H H ) in cautarea binara, este:
x A + y B H C x + y x \sum_{x\cdot A + y\cdot B \leq H} C_{x+y}^x

Presupunem, fara a restrange generalitatea, ca A B A \leq B . Daca fixam y y , valoarea maxima pentru x x este x m a x = [ H y B A ] x_{max} =[\frac{H - y\cdot B}{A}] . Deci pentru y y fixat adunam la numarul posibil de noduri:
x = 0 x m a x C x + y x = x = 0 x m a x C x + y y \sum_{x=0}^{x_{max}} C_{x+y}^x = \sum_{x=0}^{x_{max}} C_{x+y}^y .

Pentru a restrange expresia de mai sus, vom incerca o interpretare intuitiva a formulei. Amintim formula “stars and bars”: C n + m 1 m 1 = C_{n+m-1}^{m-1} = numarul de moduri de a imparti n n bile identice in m m cutii diferite. Schimband notatiile C x + y y C_{x+y}^{y} reprezinta numarul de moduri de a distribui x x bile identice in y + 1 y+1 cutii diferite. In concluzie, suma de mai sus se traduce in “cate moduri de a distribui cel mult x m a x x_{max} bile identice in y + 1 y+1 cutii diferite” exista. Dar acest lucru este echivalent cu a numara in cate moduri putem imparti x m a x x_{max} bile in y + 2 y+2 cutii (ultima cutie reprezinta bilele “aruncate”). Obtinem formula restransa:
x = 0 x m a x C x + y y = C x m a x + y + 1 y + 1 \sum_{x=0}^{x_{max}} C_{x+y}^y = C_{x_{max} + y + 1}^{y + 1} .

Ultima optimizare vine din observatia ca foarte multe din combinarile de mai sus au valori mari. Pentru n > 100 n > 100 si k > 5 k > 5 , avem C n k > 1 0 9 C_n^k > 10^9 . Deci daca ajungem la o astfel de combinare in timpul calculului, putem sa il oprim si sa stabilim ca inaltimea fixata este mai mare sau egala cu cea cautata.

Complexitatea finala va fi aproximativ O ( l o g   H l o g   N + C ) O(log\ H \cdot log\ N + C) , unde C C este numarul de combinari care trebuie precalculate (in jur de 10.000 10.000 ).

Relatii de recurenta. Calcul matriceal

Problema 8 (KFib)

Problema ne cere sa determinam al K K -lea termen al sirului Fibonacci ( F K F_K ). Consideram urmatorul vector cu 2 2 elemente: ( F i 1 F i ) \begin{pmatrix} F_{i-1} \\ F_i \end{pmatrix} , continand doua numere consecutive din sirul Fibonacci. Printr-o inmultire cu o matrice de dimensiune 2 × 2 2 \times 2 , putem obtine vectorul continand termenii F i F_i si F i + 1 F_{i+1} .

( 0 1 1 1 ) ( F i 1 F i ) = ( F i F i 1 + F i ) = ( F i F i + 1 ) \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} \cdot \begin{pmatrix} F_{i-1} \\ F_i \end{pmatrix} = \begin{pmatrix} F_i \\ F_{i-1} + F_i \end{pmatrix} = \begin{pmatrix} F_i \\ F_{i+1} \end{pmatrix}

Folosind proprietatea de asociativitate a inmultirii de matrici obtinem:
( 0 1 1 1 ) K ( F 0 F 1 ) = ( F K F K + 1 ) \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}^K \cdot \begin{pmatrix} F_{0} \\ F_1 \end{pmatrix} = \begin{pmatrix} F_K \\ F_{K+1} \end{pmatrix}

Putem determina deci F K F_K in complexitate O ( l o g   K ) O(log\ K) folosind metoda de ridicare la putere in timp logaritmic a matricei patratice. O implementare a acestei idei o puteti accesa aici.

Problema 9 (Iepuri)

Notam cu I n I_n numarul de iepuri din ziua n n .
I 0 = X I_0=X , I 1 = Y I_1=Y , I 2 = Z I_2=Z
I n = A I n 1 + B I n 2 + C I n 3 I_n = A*I_{n-1} + B*I_{n-2} + C*I_{n-3}

Construim matricea M = ( 0 1 0 0 0 1 C B A ) M = \begin{pmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ C & B & A \end{pmatrix}
Avem: ( 0 1 0 0 0 1 C B A ) ( I n 3 I n 2 I n 1 ) = ( I n 2 I n 1 I n ) \begin{pmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ C & B & A \end{pmatrix} \cdot \begin{pmatrix} I_{n-3} \\ I_{n-2} \\ I_{n-1} \end{pmatrix} = \begin{pmatrix} I_{n-2} \\ I_{n-1} \\ I_{n} \end{pmatrix}
Putem sa aplicam inca o data ridicarea la putere in timp logaritmic pentru formula:
( 0 1 0 0 0 1 C B A ) N ( I 0 I 1 I 2 ) = ( I N I N + 1 I N + 2 ) \begin{pmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ C & B & A \end{pmatrix}^{N} \cdot \begin{pmatrix} I_{0} \\ I_{1} \\ I_{2} \end{pmatrix} = \begin{pmatrix} I_{N} \\ I_{N+1} \\ I_{N+2} \end{pmatrix}

Problema 10 (Ecu)

Trecerea de la valorile de la iteratia i i : ( x 1 ( i ) , x 2 ( i ) , , x N ( i ) x_1^{(i)}, x_2^{(i)}, \ldots, x_N^{(i)} ) la valorile de la itaratia i + 1 i+1 : ( x 1 ( i + 1 ) , x 2 ( i + 1 ) , , x N ( i + 1 ) x_1^{(i+1)}, x_2^{(i+1)}, \ldots, x_N^{(i+1)} ) se poate face printr-o inmultire cu o matrice de dimensiune N × N N \times N .

Aplicand ridicare la putere in timp logaritmic obtinem complexitatea O ( N 3   l o g   M ) O(N^3\ log\ M) . Termenul N 3 N^3 vine de la complexitatea de a inmulti doua matrici de dimensiune N × N N \times N .

Problema 11 (Recurenta2)

Notam S i = j = 1 i j X j S_i = \sum\limits_{j=1}^i j \cdot X_j . Recurenta pentru S i + 1 = S i + ( i + 1 ) X i + 1 S_{i+1} = S_{i} + (i+1) \cdot X_{i+1} .

Il putem explicita pe X i + 1 X_{i+1} in functie de termenii anteriori:
S i + 1 = S i + ( i + 1 ) X i 1 B + ( i + 1 ) X i A + ( i + 1 ) C S_{i+1} = S_{i} + (i+1) \cdot X_{i-1} \cdot B + (i+1) \cdot X_{i} \cdot A + (i + 1) \cdot C .

Putem organiza aceasta recurenta folosind urmatoarea matrice:
( 0 1 0 0 0 0 0 B A C 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 B A C 0 1 0 0 0 1 0 B A C 0 B A C 0 0 1 0 0 0 1 ) ( X i 2 X i 1 1 S i 1 i X i 2 i X i 1 i ) = ( X i 1 X i 1 S i ( i + 1 ) X i 1 ( i + 1 ) X i i + 1 ) \begin{pmatrix} 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ B & A & C & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & B & A & C \\ 0 & 1 & 0 & 0 & 0 & 1 & 0 \\ B & A & C & 0 & B & A & C \\ 0 & 0 & 1 & 0 & 0 & 0 & 1 \\ \end{pmatrix} \cdot \begin{pmatrix} X_{i-2} \\ X_{i-1} \\ 1 \\ S_{i-1} \\ i \cdot X_{i-2} \\ i \cdot X_{i-1} \\ i \end{pmatrix} = \begin{pmatrix} X_{i-1} \\ X_{i} \\ 1 \\ S_{i} \\ (i+1) \cdot X_{i-1} \\ (i + 1) \cdot X_{i} \\ i + 1 \end{pmatrix}
Putem sa determinam S N S_N in O ( l o g   N ) O(log\ N) folosind exponentiere in timp logaritmic de matrice.

Principiul includerii si excluderii

Fie A , B , C , A 1 , A 2 , , A n A, B, C, A_1, A_2, \ldots, A_n multimi finite. Principiul includerii si excluderii cuprinde urmatoarele identitati:

enter image description here

Problema 12 (Pinex)

Problema este o aplicatie simpla a principiului includerii si excluderii.
Fie p 1 , p 2 , , p n p_1, p_2, \ldots, p_n divizorii primi ai lui B B .
Notam cu M i = { x 2 x A , p i x } M_i = \{x | 2 \leq x \leq A, p_i | x\} (multimea numerelor mai mici decat A A , divizibile cu p i p_i ).

Fie X A X \leq A , X X este prim cu B B , adica ( X , B ) = 1 (X, B) = 1 , daca si numai daca i = 1 , n \forall i=\overline{1, n} , X X nu este divizibil cu p i p_i . Putem deci observa ca numarul de numere prime cu B B mai mici decat A A este:

A A 1 A 2 A n A - |A_1 \cup A_2 \cup \ldots \cup A_n|

Dar putem calcula A 1 A 2 A n |A_1 \cup A_2 \cup \ldots \cup A_n| folosind principiul includerii si excluderii. Pentru aceasta trebuie sa stabilim care este cardinalul unei intersectii oarecare de astfel de multimi. Fie 1 i 1 < < i k n 1 \leq i_1 < \ldots < i_k \leq n , 1 k n 1 \leq k \leq n , care este cardinalul multimii A i 1 A i 2 A i k |A_{i_1} \cap A_{i_2} \cap \ldots \cap A_{i_k}| ?

Ce inseamna ca un numar X X se afla in multimea A i 1 A i 2 A i k |A_{i_1} \cap A_{i_2} \cap \ldots \cap A_{i_k}| ? Inseamna ca X X se divide cu p i 1 , , p i k p_{i_1}, \ldots, p_{i_k} , dar toate aceste valori sunt numere prime, deci X X se divide si cu p i 1 p i 2 p i k p_{i_1} \cdot p_{i_2} \cdot \ldots \cdot p_{i_k} .

Cate numere A \leq A se divid cu un numar D D ? [ A D ] [\frac{A}{D}]

Avem deci: A i 1 A i 2 A i k = [ A p i 1 p i 2 p i k ] |A_{i_1} \cap A_{i_2} \cap \ldots \cap A_{i_k}| = [\frac{A}{p_{i_1} \cdot p_{i_2} \cdot \ldots \cdot p_{i_k}}] .

Sirurile de indici 1 i 1 < < i k n 1 \leq i_1 < \ldots < i_k \leq n , 1 k n 1 \leq k \leq n pot fi generate in O ( 2 n ) O(2^n) folosind backtracking sau iterand prin toate numerele cu n n biti, urmand ca pentru o configuratie cardinalul intersectiei sa fie calculat in O ( n ) O(n) . Cum n n numarul de numere prime distincte care il divid pe B B este mic, solutia se incadreaza fara probleme in timp.

Problema 13 (Indep)

Notam cu A A sirul A 1 , , A n A_1, \ldots, A_n din enunt.
Notam cu V M A X VMAX valoarea maxima din A A ( V M A X 1000 VMAX \leq 1000 ).
Notam cu D X = { a a A , X a } D_X = \{a | a\in A, X|a\} (multimea numerelor din A A divizibile cu X X ).
Notam cu Z X = 2 D X 1 Z_X = 2^{|D_X|} - 1 , numarul de subsiruri nevide ale lui A A in care toate elementele sunt divizibile cu X X .

Fie p 1 , , p k p_1, \ldots,p_k toate numerele prime mai mici decat V M A X VMAX .
Un subsir al lui A A are cmmdc-ul 1 1 daca si numai daca p i , i = 1 , k \forall p_i, i=\overline{1, k} exista un element al subsirului care nu este divizibil cu p i p_i .

Folsind principiul includerii si excluderii, observam ca numarul cautat de subsiruri este:
R = Z 1 Z p 1 Z p 2 Z p k + Z p 1 p 2 + Z p 1 p 3 + + Z p k 1 p k Z p 1 p 2 p 3 R = Z_1 - Z_{p_1} - Z_{p_2} - \ldots - Z_{p_k} + Z_{p_1 \cdot p_2} + Z_{p_1 \cdot p_3} + \ldots + Z_{p_{k-1} \cdot p_k} - Z_{p_1 \cdot p_2 \cdot p_3} - \ldots

O complexitate de O ( 2 k ) O(2^k) ar fi prea mare pentru a obtine raspunsul. Insa observam ca ne intereseaza Z X Z_X doar pentru X V M A X X \leq VMAX . Cu alte cuvinte ne uitam la toate numerele din intervalul [ 1 , V M A X ] [1, VMAX] care se scriu ca produs de numere prime distincte. Daca X X se scrie ca un produs de un numar impar de numere prime distincte scadem din raspuns Z X Z_X , iar daca se scrie ca un produs de un numar par de numere prime distincte adunam Z X Z_X la raspuns.

Ca o ultima observatie, intrucat D X N 500 |D_X| \leq N \leq 500 , numerle Z X Z_X pot depasi orice tip intreg din C++, deci avem nevoie sa mentinem Z X Z_X folosind numere mari.

Problema 14 (Cowfood)

Numarul de experimente cautat il vom putea calcula ca T F T-F , unde T T reprezinta numarul total de experimente valide (valide in legatura cu limita S S ), iar F F reprezinta numarul de experimente valide care sigur vor esua.

Pentru un experiment X X notam F X F_X multimea experimentelor care vor esua conform experimentului X X . Astfel pentru un experiment A = ( a 1 , , a k ) A = (a_1, \ldots, a_k) , toate experimentele B = ( b 1 , , b k ) B=(b_1, \ldots, b_k) cu a 1 b 1 , a 2 b 2 , , a k b k a_1 \leq b_1, a_2 \leq b_2, \ldots, a_k \leq b_k apartin multimii F A F_A .

Observam ca F = F E 1 F E 2 F E n F = |F_{E_1} \cup F_{E_2} \cup \ldots \cup F_{E_n}| , unde E i E_i sunt experimentele din input.
Folosind principiul includerii si excluderii: F = F E 1 + F E 2 + + F E n F E 1 F E 2 F E 1 F E 3 F E n 1 F E n + + ( 1 ) n 1 F E 1 F E n F = |F_{E_1}| + |F_{E_2}| + \ldots + |F_{E_n}| - |F_{E_1} \cap F_{E_2}| - |F_{E_1} \cap F_{E_3}| - \ldots -|F_{E_{n-1}} \cap F_{E_n}| + \ldots + (-1)^{n-1}|F_{E_1} \cap \ldots \cap F_{E_n}| .

Ce inseamna intersectia in acest context?
Daca A = ( a 1 , , a k ) A=(a_1, \ldots, a_k) si B = ( b 1 , , b k ) B=(b_1, \ldots, b_k) sunt doua experimente, F A F B F_A \cap F_B corespunde multimii experimentelor care vor esua atat conform lui A A cat si conform lui B B , echivalent cu a considera experimentele care vor esua conform experimentului ( m a x ( a 1 , b 1 ) , m a x ( a 2 , b 2 ) , , m a x ( a k , b k ) ) (max(a_1, b_1), max(a_2, b_2), \ldots, max(a_k, b_k)) .

Astfel pentru a calcula formula putem folosi backtracking pentru a genera toate submultimile de experimente din input si a reduce aceasta submultime la un singur experiment echivalent.

Ramane sa stabilim cum putem calcula F X |F_X| pentru orice experiment X = ( x 1 , , x k ) X=(x_1, \ldots, x_k) . Pentru a obtine un experiment esuat putem incrementa oricare dintre valorile x i x_i atata timp cat suma lor nu depaseste S S . Deci putem realiza cel mult S ( x 1 + + x k ) S - (x_1 + \ldots + x_k) astfel de incrementari. Este echivalent cu a numara “in cate moduri pot distribui cel mult S ( x 1 + + x k ) S - (x_1 + \ldots + x_k) bile identice in k k cutii diferite”.

Am vazut la problema Provocare cum ca numarul de moduri de a distribui cel mult i i bile identice in j j cutii diferite este egal cu numarul de moduri de a distribui exact i i bile identice in j + 1 j+1 cutii (ultima cutie reprezinta bilele pe care le “aruncam/ignoram”). Acest lucru se poate calcula folosind “stars and bars”: C i + j j C_{i+j}^j .

Pentru a determina T T , numarul total de experimente valide, putem determina F E 0 |F_{E_0}| , unde E 0 = ( 0 , 0 , , 0 ) E_0 = (0, 0, \ldots, 0) , adica cate experimente esueaza conform experimentului cu toate valorile 0 0 (toate experimentele esueaza in acest caz).

Complexitatea asteptata este O ( K 2 N + S ) O(K \cdot 2^N + S) .

Bibliografie