This shows you the differences between two versions of the page.
|
pa:laboratoare:laborator-02 [2026/03/15 17:44] matei.mantu Explain binary exponentiation |
pa:laboratoare:laborator-02 [2026/03/15 19:10] (current) aureliu.antonie [Gardurile lui Gigel] |
||
|---|---|---|---|
| Line 359: | Line 359: | ||
| * $dp[i] = (dp[i-1] + dp[i-4]) \ \% \ MOD$ | * $dp[i] = (dp[i-1] + dp[i-4]) \ \% \ MOD$ | ||
| * | * | ||
| - | <note> Așa cum am zis în secțiunea de [[http://ocw.cs.pub.ro/courses/pa/laboratoare/laborator-04?&#sfaturireguli|sfaturi și reguli]] vrem să facem o **parționare** după un anumit **criteriu**: în cazul problemei de față, criteriul de parționare este dacă gardul se termină cu o scândură verticală sau orizontală. | + | <note> Așa cum am zis în secțiunea de [[http://ocw.cs.pub.ro/courses/pa/laboratoare/laborator-02?&#sfaturireguli|sfaturi și reguli]] vrem să facem o **parționare** după un anumit **criteriu**: în cazul problemei de față, criteriul de parționare este dacă gardul se termină cu o scândură verticală sau orizontală. |
| - | De asemenea, tot în secțiunea [[http://ocw.cs.pub.ro/courses/pa/laboratoare/laborator-04?&#sfaturireguli|sfaturi și reguli]] am precizat că nu vrem **să număram un obiect** (un mod de a construi gardul) **de două ori**. Recurența noastră (dp[i] = dp[i-1] + dp[i-4]) nu ia un obiect de două ori pentru că orice soluție care vine din dp[i-4] e diferită de alta care vine din dp[i-1] pentru că diferă în cel puțin ultima scândură așezată) </note> | + | De asemenea, tot în secțiunea [[http://ocw.cs.pub.ro/courses/pa/laboratoare/laborator-02?&#sfaturireguli|sfaturi și reguli]] am precizat că nu vrem **să număram un obiect** (un mod de a construi gardul) **de două ori**. Recurența noastră (dp[i] = dp[i-1] + dp[i-4]) nu ia un obiect de două ori pentru că orice soluție care vine din dp[i-4] e diferită de alta care vine din dp[i-1] pentru că diferă în cel puțin ultima scândură așezată) </note> |
| == Implementare recurență == | == Implementare recurență == | ||
| Line 498: | Line 498: | ||
| $$S_i = S_{k}C^{i -k}$$ | $$S_i = S_{k}C^{i -k}$$ | ||
| - | Pentru a aduce un plus de viteză, vom folosi un truc numit **exponențiere rapidă**. Pe scurt, vom ridica o valoare(notată $a$) la puterea n, împărțind n folosind reprezentarea sa binară. | + | Pentru a aduce un plus de viteză, vom folosi un truc numit [[https://en.wikipedia.org/wiki/Exponentiation_by_squaring|exponențiere rapidă]]. Pe scurt, vom ridica o valoare(notată $a$) la puterea n, împărțind n folosind reprezentarea sa binară. |
| - | De exemplu, dacă am vrea să calculăm | + | De exemplu, dacă am vrea să calculăm: |
| $$ 5^{13} = 5^{1101_2}= 5^8 * 5^4 * 5^1 $$ | $$ 5^{13} = 5^{1101_2}= 5^8 * 5^4 * 5^1 $$ | ||
| Exponentul are exact $\lfloor log_2(n) \rfloor + 1$ cifre în baza 2, deci vom avea nevoie de $O(log(n))$ înmulțiri, fiind condiționați de faptul că trebuie să cunoaștem $a^1, a^2, a^4, etc.$ Din fericire, putem calcula rapid acești factori prin ridicarea la pătrat a elementului precedent. | Exponentul are exact $\lfloor log_2(n) \rfloor + 1$ cifre în baza 2, deci vom avea nevoie de $O(log(n))$ înmulțiri, fiind condiționați de faptul că trebuie să cunoaștem $a^1, a^2, a^4, etc.$ Din fericire, putem calcula rapid acești factori prin ridicarea la pătrat a elementului precedent. | ||
| - | În final, putem implementa un algoritm iterativ pentru calcularea rezultatului $a^n$ iterând prin cifrele din baza 2 ale lui n și înmulțind cu ${a^2}^{k}$ atunci când cifra curentă este 1.(pentru viteză, vom folosi operații pe biți) | + | În final, putem implementa un algoritm iterativ pentru calcularea rezultatului $a^n$ iterând prin cifrele din baza 2 ale lui n și înmulțind cu ${a^2}^{k}$ atunci când cifra curentă este 1(pentru viteză, vom folosi operații pe biți în loc de o iterare propriu zisă prin cifre). |
| Mai jos putem vedea o implementare in C++: | Mai jos putem vedea o implementare in C++: | ||
| Line 526: | Line 526: | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| + | Acest truc poate fi folosit pentru orice tip de date pentru care înmulțirea este asociativă(inclusiv matrice). | ||
| + | |||
| Obținem astfel o soluție cu următoarele complexități: | Obținem astfel o soluție cu următoarele complexități: | ||
| * ** complexitate temporală **: $T = O(KMAX^3 * log(n))$ | * ** complexitate temporală **: $T = O(KMAX^3 * log(n))$ | ||