All Euler problems
Project Euler

Cuboid Layers

The minimum number of cubes to cover every visible face on a cuboid measuring 3 x 2 x 1 is twenty-two. If we then add a second layer to this solid it would require forty-six cubes, the third layer...

Source sync May 21, 2026
Problem #0126
Level Level 06
Solved By 5,587
Languages C++, Python
Answer 18522
Length 346 words
optimizationbrute_forcegeometry

Problem Statement

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

The minimum number of cubes to cover every visible face on a cuboid measuring \(3 \times 2 \times 1\) is twenty-two.

PIC

If we then add a second layer to this solid it would require forty-six cubes to cover every visible face, the third layer would require seventy-eight cubes, and the fourth layer would require one-hundred and eighteen cubes to cover every visible face.

However, the first layer on a cuboid measuring \(5 \times 1 \times 1\) also requires twenty-two cubes; similarly the first layer on cuboids measuring \(5 \times 3 \times 1\), \(7 \times 2 \times 1\), and \(11 \times 1 \times 1\) all contain forty-six cubes.

We shall define \(C(n)\) to represent the number of cuboids that contain \(n\) cubes in one of its layers. So \(C(22) = 2\), \(C(46) = 4\), \(C(78) = 5\), and \(C(118) = 8\).

It turns out that \(154\) is the least value of \(n\) for which \(C(n) = 10\).

Find the least value of \(n\) for which \(C(n) = 1000\).

Problem 126: Cuboid Layers

Mathematical Development

Theorem 1 (Layer formula). For a cuboid with dimensions a×b×ca \times b \times c (a≤b≤ca \leq b \leq c), the number of cubes in the kk-th layer (k≥1k \geq 1) is

f(a,b,c,k)=2(ab+bc+ac)+4(a+b+c)(k−1)+4(k−1)(k−2).f(a, b, c, k) = 2(ab + bc + ac) + 4(a + b + c)(k-1) + 4(k-1)(k-2).

Proof. The total volume enclosed by kk layers around an a×b×ca \times b \times c cuboid (including the cuboid itself) is

V(k)=(a+2k)(b+2k)(c+2k)−abcV(k) = (a + 2k)(b + 2k)(c + 2k) - abc

where the subtraction accounts for the hollow interior. The number of cubes in layer kk alone is

f(a,b,c,k)=V(k)−V(k−1).f(a,b,c,k) = V(k) - V(k-1).

Expanding:

V(k)=(a+2k)(b+2k)(c+2k)−abc,V(k−1)=(a+2k−2)(b+2k−2)(c+2k−2)−abc.\begin{align*} V(k) &= (a+2k)(b+2k)(c+2k) - abc, \\ V(k-1) &= (a+2k-2)(b+2k-2)(c+2k-2) - abc. \end{align*}

Let u=2ku = 2k. Then V(k)−V(k−1)V(k) - V(k-1) equals:

(a+u)(b+u)(c+u)−(a+u−2)(b+u−2)(c+u−2).\begin{align*} &(a+u)(b+u)(c+u) - (a+u-2)(b+u-2)(c+u-2). \end{align*}

Expanding both products and subtracting, collecting terms in powers of u=2ku = 2k:

f=2(ab+bc+ac)+4(a+b+c)(k−1)+4(k−1)(k−2).f = 2(ab+bc+ac) + 4(a+b+c)(k-1) + 4(k-1)(k-2).

Verification: For k=1k = 1: f=2(ab+bc+ac)f = 2(ab + bc + ac), which is the surface area of the cuboid. For (a,b,c,k)=(3,2,1,1)(a,b,c,k) = (3,2,1,1): f=2(6+2+3)=22f = 2(6+2+3) = 22. For k=2k = 2: f=22+4(6)(1)+0=46f = 22 + 4(6)(1) + 0 = 46. Both match the problem statement. □\square

Lemma 1 (Monotonicity in kk). For fixed (a,b,c)(a, b, c), f(a,b,c,k)f(a, b, c, k) is strictly increasing in kk.

Proof. f(a,b,c,k+1)−f(a,b,c,k)=4(a+b+c)+4(2k−1)>0f(a,b,c,k+1) - f(a,b,c,k) = 4(a+b+c) + 4(2k-1) > 0 for all k≥1k \geq 1 and positive dimensions. □\square

Lemma 2 (Enumeration bounds). To find all (a,b,c,k)(a, b, c, k) with f(a,b,c,k)≤Nf(a, b, c, k) \leq N:

  • aa: from 11 while 2a2≤N2a^2 \leq N (minimum layer for cube a×a×aa \times a \times a).
  • bb: from aa while 2(ab+b2)≤N2(ab + b^2) \leq N.
  • cc: from bb while 2(ab+bc+ac)≤N2(ab + bc + ac) \leq N (the k=1k=1 value).
  • kk: from 11 while f(a,b,c,k)≤Nf(a,b,c,k) \leq N.

Proof. For k=1k = 1 with a=b=ca = b = c: f=6a2f = 6a^2, so 6a2≤N6a^2 \leq N gives a≤N/6a \leq \sqrt{N/6}, which is weaker than 2a2≤N2a^2 \leq N (obtained from f≥2(a2+a⋅b+...)≥2a2f \geq 2(a^2 + a \cdot b + ...) \geq 2a^2 with b=c=ab = c = a). The other bounds follow from f≥2(ab+bc+ac)f \geq 2(ab + bc + ac) (the k=1k=1 minimum). □\square

Editorial

Once the closed formula for the kk-th layer is available, the problem becomes a counting task: how many tuples (a,b,c,k)(a,b,c,k) produce each layer size nn? Because the layer size is monotone in every parameter, the search can be bounded very tightly. The constraints a≤b≤ca \le b \le c avoid duplicate cuboids, and for each fixed cuboid the layer index is increased only until the formula exceeds the global limit.

The implementation maintains a frequency array C[n]C[n] telling how many cuboids realize a layer of size nn. It enumerates every feasible ordered cuboid, walks through its successive layers, increments the corresponding counts, and finally scans upward for the first value where the count reaches 1000.

Pseudocode

Choose a search limit large enough to contain the first answer.
Initialize a counting array C over all layer sizes up to that limit.

Enumerate side lengths a, b, c with a <= b <= c, stopping each loop as soon as the first layer is already too large.
For each cuboid:
    Increase the layer index k from 1 upward.
    Evaluate the layer-size formula.
    If the value exceeds the search limit, stop increasing k for this cuboid.
    Otherwise increment C at that layer size.

Scan the counting array from small to large and return the first n with C(n) = 1000.

Complexity Analysis

  • Time: The four nested loops enumerate all tuples (a,b,c,k)(a, b, c, k) with f≤Nf \leq N. The number of such tuples is O(Nlog⁡N)O(N \log N) empirically. Total: O(Nlog⁡N)O(N \log N).
  • Space: O(N)O(N) for the counting array CC.

Answer

18522\boxed{18522}

Code

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

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

int main() {
    const int LIMIT = 20000;
    vector<int> C(LIMIT + 1, 0);

    // f(a,b,c,k) = 2(ab+bc+ac) + 4(a+b+c)(k-1) + 4(k-1)(k-2)
    for (int a = 1; 2LL * a * a <= LIMIT; a++) {
        for (int b = a; 2LL * (a * b + b * b) <= LIMIT; b++) {
            for (int c = b; 2LL * ((long long)a * b + (long long)b * c + (long long)a * c) <= LIMIT; c++) {
                long long base = 2LL * (a * b + b * c + a * c);
                long long edge = 4LL * (a + b + c);
                for (int k = 1; ; k++) {
                    long long val = base + edge * (k - 1) + 4LL * (k - 1) * (k - 2);
                    if (val > LIMIT) break;
                    C[(int)val]++;
                }
            }
        }
    }

    for (int n = 1; n <= LIMIT; n++) {
        if (C[n] == 1000) {
            cout << n << endl;
            return 0;
        }
    }

    return 0;
}