Clasa a XII-a · Matematică pentru programareRead in English

Exponențierea rapidă în C++

În engleză: Fast exponentiation

O(log n)C++1750 de linii3 exemple

Ideea

Calculăm a^n cu aproximativ log2(n) înmulțiri în loc de n. Ideea: a^n = (a^2)^(n/2) dacă n este par și a^n = a * a^(n-1) dacă n este impar. Varianta iterativă parcurge biții lui n: când bitul curent este 1 înmulțim rezultatul cu baza, apoi ridicăm baza la pătrat și trecem la bitul următor (n = n / 2). De exemplu, 3^13 = 3^8 * 3^4 * 3^1, pentru că 13 = 1101 în baza 2. Programul presupune că rezultatul încape în long long.

Descrierea în engleză

We compute a^n with about log2(n) multiplications instead of n. The idea: a^n = (a^2)^(n/2) if n is even and a^n = a * a^(n-1) if n is odd. The iterative version walks the bits of n: when the current bit is 1 we multiply the result by the base, then square the base and move to the next bit (n = n / 2). For example, 3^13 = 3^8 * 3^4 * 3^1, because 13 = 1101 in base 2. The program assumes the result fits in long long.

Complexitate
O(log n)
Clasa
Clasa a XII-a (Grade 12)

Exemple

Exemplul 1

Intrare

2 62

Ieșire așteptată

4611686018427387904
Exemplul 2

Intrare

3 13

Ieșire așteptată

1594323
Exemplul 3

Intrare

5 0

Ieșire așteptată

1

Codul C++

Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.

exponentiere-rapida.cpp
/*
 * Titlu: Exponențierea rapidă
 * Clasa: 12
 * Capitol: Matematică pentru programare
 * Descriere: Calculăm a^n cu aproximativ log2(n) înmulțiri în loc de n.
 *            Ideea: a^n = (a^2)^(n/2) dacă n este par și a^n = a * a^(n-1) dacă n
 *            este impar. Varianta iterativă parcurge biții lui n: când bitul
 *            curent este 1 înmulțim rezultatul cu baza, apoi ridicăm baza la
 *            pătrat și trecem la bitul următor (n = n / 2). De exemplu,
 *            3^13 = 3^8 * 3^4 * 3^1, pentru că 13 = 1101 în baza 2.
 *            Programul presupune că rezultatul încape în long long.
 * Complexitate: O(log n)
 *
 * Exemplu
 * Intrare: 2 62
 * Ieșire: 4611686018427387904
 *
 * Exemplu
 * Intrare: 3 13
 * Ieșire: 1594323
 *
 * Exemplu
 * Intrare: 5 0
 * Ieșire: 1
 */
#include <iostream>
using namespace std;

long long putere(long long baza, long long exponent)
{
    long long rezultat = 1;
    while (exponent > 0)
    {
        if (exponent % 2 == 1)
            rezultat = rezultat * baza;
        exponent = exponent / 2;
        if (exponent > 0) // evităm o ridicare la pătrat inutilă, care ar putea depăși
            baza = baza * baza;
    }
    return rezultat;
}

int main()
{
    long long a, n;
    cin >> a >> n;
    cout << putere(a, n) << '\n';
    return 0;
}

Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.