Clasa a XII-a · Matematică pentru programareRead in English
Exponențierea rapidă în C++
În engleză: Fast exponentiation
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)
- Capitol
- Matematică pentru programare
Exemple
Intrare
2 62
Ieșire așteptată
4611686018427387904
Intrare
3 13
Ieșire așteptată
1594323
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.
/*
* 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.