All Euler problems
Project Euler

Efficient Exponentiation

The most efficient way to compute x^n uses the minimum number of multiplications, where each multiplication computes x^(a_i + a_j) from previously computed powers x^(a_i) and x^(a_j). This minimum...

Source sync May 21, 2026
Problem #0122
Level Level 05
Solved By 9,020
Languages C++, Python
Answer 1582
Length 536 words
searchoptimizationbrute_force

Problem Statement

This archive keeps the full statement, math, and original media on the page.

The most naive way of computing \(n^{15}\) requires fourteen multiplications: \[n \times n \times \cdots \times n = n^{15}.\] But using a "binary" method you can compute it in six multiplications: \begin {align*} n \times n &= n^2\\ n^2 \times n^2 &= n^4\\ n^4 \times n^4 &= n^8\\ n^8 \times n^4 &= n^{12}\\ n^{12} \times n^2 &= n^{14}\\ n^{14} \times n &= n^{15} \end {align*}

However it is yet possible to compute it in only five multiplications: \begin {align*} n \times n &= n^2\\ n^2 \times n &= n^3\\ n^3 \times n^3 &= n^6\\ n^6 \times n^6 &= n^{12}\\ n^{12} \times n^3 &= n^{15} \end {align*}

We shall define \(m(k)\) to be the minimum number of multiplications to compute \(n^k\); for example \(m(15) = 5\).

Find \(\displaystyle \sum \limits _{k = 1}^{200} m(k)\).

Problem 122: Efficient Exponentiation

Mathematical Development

Definition 1 (Addition chain). An addition chain for a positive integer nn is a finite sequence 1=a0<a1<⋯<ar=n1 = a_0 < a_1 < \cdots < a_r = n such that for each 1≤k≤r1 \le k \le r, there exist indices 0≤i≤j<k0 \le i \le j < k with ak=ai+aja_k = a_i + a_j. The length of the chain is rr.

Definition 2. Let m(n)m(n) denote the length of a shortest addition chain for nn. By convention, m(1)=0m(1) = 0.

Theorem 1 (Lower bound). For all n≥1n \ge 1, m(n)≥⌈log⁡2n⌉m(n) \ge \lceil \log_2 n \rceil.

Proof. At each step kk, since ak=ai+aj≤2ak−1a_k = a_i + a_j \le 2a_{k-1} (the largest element can at most double), we have by induction ak≤2ka0=2ka_k \le 2^k a_0 = 2^k. In particular, n=ar≤2rn = a_r \le 2^r, so r≥log⁡2nr \ge \log_2 n. Since rr is an integer, r≥⌈log⁡2n⌉r \ge \lceil \log_2 n \rceil. □\square

Theorem 2 (Upper bound via binary method). For all n≥1n \ge 1, m(n)≤⌊log⁡2n⌋+ν(n)−1m(n) \le \lfloor \log_2 n \rfloor + \nu(n) - 1, where ν(n)\nu(n) denotes the number of 11-bits (Hamming weight) of nn.

Proof. The binary method scans the binary representation n=(bsbs−1⋯b1b0)2n = (b_s b_{s-1} \cdots b_1 b_0)_2 (with bs=1b_s = 1) from the most significant bit to the least. For each bit position ii from s−1s-1 down to 00: perform a doubling (add the current value to itself). If bi=1b_i = 1, additionally add a0=1a_0 = 1. This produces a valid addition chain with ⌊log⁡2n⌋\lfloor \log_2 n \rfloor doublings and ν(n)−1\nu(n) - 1 small additions (one per 1-bit excluding the leading bit). □\square

Proposition 1 (Binary method is not always optimal). m(15)=5m(15) = 5, but the binary method uses ⌊log⁡215⌋+ν(15)−1=3+4−1=6\lfloor \log_2 15 \rfloor + \nu(15) - 1 = 3 + 4 - 1 = 6 steps.

Proof. The chain 1,2,3,6,12,151, 2, 3, 6, 12, 15 has length 5 and is valid: 2=1+12 = 1+1, 3=1+23 = 1+2, 6=3+36 = 3+3, 12=6+612 = 6+6, 15=3+1215 = 3+12. By exhaustive search (or by noting that m(15)≥⌈log⁡215⌉=4m(15) \ge \lceil \log_2 15 \rceil = 4 and verifying that no chain of length 4 reaches 15), m(15)=5m(15) = 5. □\square

Theorem 3 (IDDFS optimality). Iterative deepening depth-first search (IDDFS) with depth limit starting at ⌈log⁡2n⌉\lceil \log_2 n \rceil finds a shortest addition chain for any nn.

Proof. IDDFS is complete (it explores all chains of each length rr before incrementing rr) and optimal for uniform-cost search (the first solution found is of minimum length). The search space is finite since all chain elements lie in {1,…,n}\{1, \ldots, n\}, and the chain is strictly increasing, bounding the depth by n−1n - 1. □\square

Lemma 1 (Pruning criterion). Let the current chain be [a0,…,ad][a_0, \ldots, a_d] with depth limit rr. If ad⋅2r−d<na_d \cdot 2^{r-d} < n, no extension of this chain can reach nn, and the branch may be pruned.

Proof. Each of the remaining r−dr - d steps can at most double the current maximum. After r−dr - d doublings the maximum attainable value is ad⋅2r−da_d \cdot 2^{r-d}. If this is strictly less than nn, the target is unreachable from this state. □\square

Editorial

For a fixed target nn, the natural search space is the set of addition chains ending at nn. Since the objective is to minimize chain length, iterative deepening is a good fit: start from the information-theoretic lower bound ⌈log⁡2n⌉\lceil \log_2 n \rceil and ask whether any chain of that length exists, then increase the depth only when necessary. The first successful depth is exactly m(n)m(n).

The depth-first search extends a partial chain by adding the current largest element to an earlier element, which is enough because any valid next step in an increasing addition chain has that form. The doubling bound gives the essential pruning rule: if even repeated doubling of the current maximum cannot reach the target within the remaining depth, that branch is hopeless and can be discarded immediately.

Pseudocode

Set the total to zero.

For each target n from 1 through 200:
    Start from the lower bound ceil(log2 n).
    Repeatedly try a depth-limited search for an addition chain ending at n.
    During the search, extend the chain by adding the current maximum to one of the earlier chain values.
    Prune any branch whose current maximum, even after all remaining doublings, still cannot reach n.
    When the first successful depth is found, add it to the total.

Return the total over all targets.

Complexity Analysis

  • Time: The branching factor at depth dd is at most d+1d + 1, and the maximum depth is r≤11r \le 11 for n≤200n \le 200. Worst-case time per nn is O(rr)O(r^r), but the pruning criterion drastically reduces the effective search tree. Empirically, the total time for all n≤200n \le 200 is very modest.
  • Space: O(r)O(r) for the DFS stack and current chain, where r≤11r \le 11.

Answer

1582\boxed{1582}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_122/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int target;
vector<int> chain;

bool dfs(int depth, int maxDepth) {
    int cur = chain.back();
    if (cur == target) return true;
    if (depth == maxDepth) return false;
    if ((long long)cur << (maxDepth - depth) < target) return false;

    for (int i = depth; i >= 0; i--) {
        int nxt = cur + chain[i];
        if (nxt <= cur || nxt > target) continue;
        chain.push_back(nxt);
        if (dfs(depth + 1, maxDepth)) return true;
        chain.pop_back();
    }
    return false;
}

int shortestChain(int n) {
    if (n == 1) return 0;
    chain.clear();
    chain.push_back(1);

    int lb = 0;
    while ((1 << lb) < n) lb++;

    for (int maxDepth = lb; ; maxDepth++)
        if (dfs(0, maxDepth)) return maxDepth;
}

int main() {
    int ans = 0;
    for (int n = 1; n <= 200; n++) {
        target = n;
        ans += shortestChain(n);
    }
    cout << ans << endl;
    return 0;
}