Processing math: 100%

75786 afișări Candale Silviu (silviu) 03.05.2021
www.pbinfo.ro
Etichete: nicio etichetă

Ridicarea la putere este o operație binecunoscută, formulă uzuală fiind: An=ni=1A=A×A××Ade n ori

Un algoritm care implementează această metodă va avea complexitate liniară, O(n):

int Putere(int A , int n)
{
    int P = 1 ;
    for(int i = 1 ; i <= n ; i ++)
        P = P * A;
    return P;
}

Descriere

O metodă mai bună este cea numită exponențierea rapidă , sau ridicarea la putere în timp logaritmic, complexitatea sa fiind O(log2n). Ea se bazează pe următoarea formulă:

An={1, dacă n=0AAn1, dacă n – impar(An2)2, dacă n – par

Exemplu

Să calculăm 225:

  • 225=2224, deoarece 25 este impar
  • 224=(212)2, deoarece 24 este par
  • 212=(26)2, deoarece 12 este par
  • 26=(23)2, deoarece 6 este par
  • 23=222, deoarece 3 este impar
  • 22=(21)2, deoarece 2 este par
  • 21=220, deoarece 1 este impar
  • 20=1

Atunci în ordine inversă:

  • 21=21=2
  • 22=22=4
  • 23=24=8
  • 26=82=64
  • 212=642=4096
  • 224=40962=16777216
  • 225=216777216=33554432

Constatăm că numărul înmulțirilor efectuate este mult mai mic decât în cazul primei metode.

Implementare recursivă

Implementarea recursivă este directă:

int Putere(int A , int n)
{
    if(n == 0)
        return 1;
    if(n % 2 == 1)
        return A * Putere(A , n - 1);
    int P = Putere(A , n / 2);
    return P * P;
}

Implementare iterativă

Să considerăm A25. Să-l scriem pe 25 ca sumă de puteri ale lui 2 (orice număr natural poate fi scris ca sumă de puteri ale lui 2 într-un singur mod): 25=1+8+16.

Atunci A25=A1+8+16=A1A8A16=(A1)1=A1(A2)0=1(A4)0=1(A8)1=A8(A16)1=A16. Observăm că exponenții 0 și 1 sunt cifrele reprezentării în baza 2 a lui 25.

Se figurează următoarea idee, pentru a determina An:

  • vom determina un produs P, format din factori de forma A1, A2, A4, A8, …
  • determinăm cifrele reprezentării în baza 2 a lui n, începând cu cea mai nesemnificativă:
    • dacă cifra curentă este 1, înmulțim pe A la P, P = P * A;
    • înmulțim pe A cu el însuși, A = A * A;, obținând următoarea putere din șirul de mai sus

Implementare C++:

int Putere(int A , int n)
{
    int P = 1;
    while(n)
    {
        if(n % 2 == 1)
            P = P * A;
        A = A * A;
        n /= 2;
    }
    return P;
}

altă variantă, care folosește operațiile pe biți:

int Putere(int A , int n)
{
    int P = 1;
    for(int k = 1 ; k <= n ; k <<= 1)
    {
        if((n & k))
            P *= A;
        A = A * A;
    }
    return P;
}

Observații

  • ridicarea la putere rapidă poate fi folosită și pentru:
    • operații modulo (determinarea restului împărțirii rezultatului la o valoare dată)
    • numere mari
    • ridicarea la putere a matricelor
    • ridicarea la putere a polinoamelor

Probleme ataşate

Nr. Problema Clasa Dificultate Operații I/O
1 #2398 - Moka 9 dificilă fișiere
2 #2404 - Test 9 ușoară fișiere
75786 afișări Candale Silviu (silviu) 03.05.2021
www.pbinfo.ro
Du-te sus!