Grade 10 · RecursionCitește în română

Power of a number, recursively

Original: Puterea unui număr, recursiv

O(n)C++1762 lines2 examples

The idea

The direct version uses a^n = a * a^(n - 1) and makes n calls. The fast version halves the exponent: if n is even, a^n = (a^(n/2))^2, otherwise a^n = a * a^(n - 1). The result of a^(n/2) is computed once and kept in a variable, otherwise the gain is lost. The result and the number of calls made by each version are printed.

Original description (Romanian)

Varianta directă folosește a^n = a * a^(n - 1) și face n apeluri. Varianta rapidă înjumătățește exponentul: dacă n este par, a^n = (a^(n/2))^2, altfel a^n = a * a^(n - 1). Rezultatul lui a^(n/2) se calculează o singură dată și se păstrează într-o variabilă, altfel câștigul se pierde. Se afișează rezultatul și numărul de apeluri făcute de fiecare variantă.

Complexity
O(n) for the direct version, O(log n) for the fast one
Grade
Grade 10 (Clasa a X-a)
Chapter
Recursion

Examples

Example 1

Input

2 10

Expected output

1024 11
1024 6
Example 2

Input

3 0

Expected output

1 1
1 1

The code

Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.

putere-recursiva.cpp
/*
 * Titlu: Puterea unui număr, recursiv
 * Clasa: 10
 * Capitol: Recursivitate
 * Descriere: Varianta directă folosește a^n = a * a^(n - 1) și face n apeluri.
 *            Varianta rapidă înjumătățește exponentul: dacă n este par,
 *            a^n = (a^(n/2))^2, altfel a^n = a * a^(n - 1). Rezultatul lui
 *            a^(n/2) se calculează o singură dată și se păstrează într-o variabilă,
 *            altfel câștigul se pierde. Se afișează rezultatul și numărul de apeluri
 *            făcute de fiecare variantă.
 * Complexitate: O(n) pentru varianta directă, O(log n) pentru cea rapidă
 *
 * Exemplu
 * Intrare: 2 10
 * Ieșire:
 * 1024 11
 * 1024 6
 *
 * Exemplu
 * Intrare: 3 0
 * Ieșire:
 * 1 1
 * 1 1
 */
#include <iostream>
using namespace std;

int apeluriDirect, apeluriRapid;

long long putere(long long a, int n)
{
    apeluriDirect++;
    if (n == 0)
        return 1;
    return a * putere(a, n - 1);
}

long long putereRapida(long long a, int n)
{
    apeluriRapid++;
    if (n == 0)
        return 1;
    if (n % 2 == 0)
    {
        long long jumatate = putereRapida(a, n / 2);
        return jumatate * jumatate;
    }
    return a * putereRapida(a, n - 1);
}

int main()
{
    long long a;
    int n;
    cin >> a >> n;
    long long r1 = putere(a, n);
    cout << r1 << ' ' << apeluriDirect << '\n';
    long long r2 = putereRapida(a, n);
    cout << r2 << ' ' << apeluriRapid << '\n';
    return 0;
}

Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.