Documente Academic
Documente Profesional
Documente Cultură
Concurs de antrenament
5 februarie 2022
0. Produs
Rolul problemei a fost doar de acomodare cu interfața. Programul este compus doar din două
instrucțini: citirea, fin>>a>>b; și afișarea, fout<<a*b;. Era nevoie să se folosească tipul
long long pentru stocarea variabilelor.
1. Primelek
Aceasta a fost considerată problema cea mai ușoară din concurs. Pentru a obține valoarea
formată cu primele k cifre ale numărului dat, trebuia doar să eliminăm câteva cifre de la final.
Pentru a afla numărul cifrelor de eliminat era necesar ca anterior să aflăm numărul total de cifre.
Acest lucru se realizează cu un algoritm obișnuit de traversare a cifrelor unui număr. O
prezentare a acestui algoritm găsiți aici:
https://cppi.sync.ro/materia/lectii/cifrele%20unui%20num%C4%83r.pdf
2. Maxime
3. Cifre
O soluție care iterează prin toate numerele de k cifre nu s-ar încadra în timp.
Putem asocia fiecărui termen al sumei noastre un șir cu k elemente 0 și 1. Apoi, punem a în
dreptul cifrelor de la pozițiile pe care se află în șir 0 și b pentru celelalte poziții. Putem deci să
generăm toate submulțimile mulțimii de k elemente și apoi să construim numărul corespunzător
Centrul de Pregătire pentru Performanță în Informatică
Concurs de antrenament
5 februarie 2022
4. Alegere
Pentru a simplifica semnificativ problema este necesară următoarea observație: Dacă pentru o
mulțime de numere aplicăm repetat operația: alegem două numere distincte și îl înlocuim pe cel
mare cu diferența lor, până când toate numerele devin egale, valoarea comună la care se
ajunge este chiar cel mai mare divizor comun al valorilor aflate inițial în mulțime. O problemă
care folosește această idee este aici:
http://campion.edu.ro/arhiva/index.php?page=problem&action=view&id=642.
O descriere a mai multor algoritmi de calcul al celui mai mare divizor comun pentru două sau
mai multe numere se găsește aici: https://cppi.sync.ro/materia/lectii/euclid_fibonacci.pdf.
O primă soluție a problemei alegere este de a fixa fiecare poziție de început și apoi fiecare pas
posibil și să calculăm cmmdc pentru subșirului corespunzator. Această soluție nu se încadrează
în timp pe toate testele. O optimizare a sa ar fi ca, odată ce am stabilit poziția de început
(index), pasul să fie doar dintre divizorii valorii n-index.
Pentru a obține punctajul maxim, vom construi elementele mulțimilor invers, plecând de la
ultimul element, cu diverse valori ale lui pas și de fiecare dată facem cmmdc între elementul
curent și cmmdc din urmă. Fiecare loc în care ajungem cu cel puțin card salturi de la final este
o mulțime de luat în calcul. Astfel suntem pe structura unui algoritm asemănător cu ciurul lui
Eratostene (traversăm șirul dat de mai multe ori, dar de fiecare dată cu salturi de altă lungime).
Centrul de Pregătire pentru Performanță în Informatică
Concurs de antrenament
5 februarie 2022
5. Drum în matrice
Aceasta este o problemă de maxime parțiale în matrice și avem soluție cu timp de calcul de
ordin n2. Notăm cu A matricea dată. Pentru fiecare poziție (i,j) calculăm suma maximă pentru
elementele unui drum care se termină în poziția (i,j). Să o notăm D[i][j]. Pentru a respecta
restricția ca oricare două elemente de pe drum să nu fie într-o submatrice de latură L sau mai
mică, este suficient să calculăm D[i][j] în funcție de D[i-L][j] și D[i][j-L]. Pentru
elementele din submatricea cu colțul stânga sus (1,1) și colțul dreapta jos (L,L) valorile
D[i][j] se calculează ca fiind maximul elementelor din A din submatrice delimitată de (1,1) și
(i,j). În acest caz, D[i][j] = maxim(D[i-1][j], D[i][j-1], A[i][j]). Soluția
problemei este maximul dintre elementele matricei D.
6. Conex
Soluția brute force constă în simularea procesului de ștergere a nodurilor. Se va ține un vector
în care se vor marca nodurile șterse. Apoi, după fiecare nod șters, se va rula un DFS începând
dintr-un nod neșters arbitrar. Daca DFS-ul vizitează toate nodurile neșterse (bineînțeles
nevizitând noduri șterse pe parcurs), atunci răspunsul va fi "YES". Complexitate O(N*(N+M)):
vor fi N ștergeri și pentru fiecare ștergere rulăm un DFS.
Soluția eficientă se bazează pe ideea că păduri de mulțimi disjuncte se pot folosi pentru a
reprezenta componentele conexe ale unui graf, suportând operații de adăugare de muchii /
noduri. Astfel, similar cu problema bile de pe infoarena, se va inversa ordinea ștergerilor, astfel
încât ștergerile sa fie inserții. Deci fiecare pas inserează un nou nod în graf. Vom tine numărul
de componente conexe curente. O inserție a unui nod nou inițial adaugă o nouă componentă
conexă. Apoi se parcurg muchiile incidente nodului și se fac operații de join între componenta
curentă și componentele respective. Fiecare join reușit va scădea numărul de componente
conexe cu 1. Răspunsul la query va fi "YES" daca numărul de componente conexe curente la
un pas este 1. Complexitate O(N+M*log*(N)).
7. InvSub
În primul rând, putem considera că vom alege întotdeauna să inversăm un subșir de lungime
pară. Aceasta restricție nu va afecta lungimea maximă posibilă a unui subșir crescător.
Demonstrația este imediată: dacă am inversa un subșir de lungime impară, elementul din
Centrul de Pregătire pentru Performanță în Informatică
Concurs de antrenament
5 februarie 2022
mijlocul acestui subșir va rămâne pe aceeași poziție, și am fi ajuns în aceeași situație dacă am
fi inversat subșirul fără această poziție (deci un subșir de lungime pară).
Ne vine ideea sa încercăm să reducem această problemă la subprobleme mai mici. Însă cum
putem defini subprobleme care să se dovedească utile? Intuiția este următoarea: atunci când
interschimbăm perechea (i1, j1) stabilim ca toate modificările asupra șirului se fac doar în acest
interval, iar în afara lui, șirul A rămâne neschimbat.
Astfel, am putea încerca să definim o dinamică dp[i][j] := cea mai mare lungime posibilă a
unui subșir crescător care se poate obține în intervalul de poziții [i, j], aplicând cel mult o
dată operația de inversare pe subșir, în acest interval.
- dp[i][j][a[j]][last] cu dp[i+1][j-1][ceva>=a[j]][last]+1
- dp[i][j][first][a[i]] cu dp[i+1][j-1][first][ceva<=a[i]]+1
- dp[i][j][a[j]][a[i]] cu
dp[i+1][j-1][ceva>=a[j]][ceva<=a[i]]+2, doar dacă a[j]<=a[i]
Complexitatea finală este O(N^2 * VMAX^2), unde am notat cu VMAX valoarea maximă din
șirul A. Cum N si VMAX <= 50, această complexitate se încadrează fără probleme în limitele de
timp și spațiu.