All Euler problems
Project Euler

Sum of a Square and a Cube

Find the sum of the five smallest palindromic numbers that can each be expressed as the sum of a square and a cube (a^2 + b^3 with a >= 1, b >= 1) in exactly 4 different ways.

Source sync Apr 19, 2026
Problem #0348
Level Level 08
Solved By 3,515
Languages C++, Python
Answer 1004195061
Length 236 words
searchlinear_algebrabrute_force

Problem Statement

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

Many numbers can be expressed as the sum of a square and a cube. Some of them in more than one way.

Consider the palindromic numbers that can be expressed as the sum of a square and a cube, both greater than \(1\), in exactly \(4\) different ways.

For example, \(5229225\) is a palindromic number and it can be expressed in exactly \(4\) different ways:

\(2285^2 + 20^3\)

\(2223^2 + 66^3\)

\(1810^2 + 125^3\)

\(1197^2 + 156^3\)

Find the sum of the five smallest such palindromic numbers.

Problem 348: Sum of a Square and a Cube

Mathematical Foundation

Theorem 1 (Representation Count). For a positive integer nn, define

r(n)=#{(a,b)Z>02:a2+b3=n}.r(n) = \#\{(a, b) \in \mathbb{Z}_{>0}^2 : a^2 + b^3 = n\}.

We seek palindromic nn with r(n)=4r(n) = 4.

Proof (well-definedness). For fixed nn, the constraint b3<nb^3 < n gives b<n1/3b < n^{1/3}, so bb ranges over finitely many values. For each bb, at most one a>0a > 0 satisfies a2=nb3a^2 = n - b^3 (namely a=nb3a = \sqrt{n - b^3} if this is a positive integer). Hence r(n)r(n) is finite and computable. \square

Lemma 1 (Palindrome Structure). A dd-digit palindrome is determined by its first d/2\lceil d/2 \rceil digits. The number of dd-digit palindromes is 9×10d/219 \times 10^{\lceil d/2 \rceil - 1} (the leading digit is nonzero).

Proof. A palindrome n=a1a2adn = \overline{a_1 a_2 \cdots a_d} satisfies ai=ad+1ia_i = a_{d+1-i}. The free digits are a1,,ad/2a_1, \ldots, a_{\lceil d/2 \rceil} with a1{1,,9}a_1 \in \{1,\ldots,9\} and ai{0,,9}a_i \in \{0,\ldots,9\} for i2i \ge 2. \square

Lemma 2 (Search Bound). Since we need only 5 palindromes, and empirically the answer involves palindromes below 10910^{9}, we search palindromes up to L=109L = 10^{9}. For each palindrome n<Ln < L:

  • bb ranges from 1 to (L1)1/3999\lfloor (L-1)^{1/3} \rfloor \approx 999
  • Checking whether nb3n - b^3 is a perfect square costs O(1)O(1) via integer square root

Proof. b3<n<109b^3 < n < 10^9 implies b<103b < 10^3. Computing nb3\lfloor \sqrt{n - b^3} \rfloor and verifying its square equals nb3n - b^3 is O(1)O(1) arithmetic. \square

Editorial

We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.

Pseudocode

    results = []

    for d = 1, 2, 3, ...: // number of digits
        for each d-digit palindrome n (in increasing order):
            count = 0
            For b from 1 to floor(n^(1/3)):
                remainder = n - b^3
                If remainder <= 0 then stop this loop
                a = isqrt(remainder)
                If a * a == remainder and a >= 1 then
                    count += 1
                If count > target_count then stop this loop

            If count == target_count then
                results.append(n)
                If len(results) == num_needed then
                    Return sum(results)

Complexity Analysis

  • Time: O(PL1/3)O(P \cdot L^{1/3}) where PP is the number of palindromes checked and LL is the search bound. With P105P \approx 10^5 palindromes below 10910^9 and L1/3103L^{1/3} \approx 10^3, total is O(108)O(10^8).
  • Space: O(1)O(1) beyond storing the results (palindromes are generated on the fly).

Answer

1004195061\boxed{1004195061}

Code

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

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

bool is_palindrome(long long n) {
    string s = to_string(n);
    string r = s;
    reverse(r.begin(), r.end());
    return s == r;
}

int main() {
    // We search palindromes up to some limit
    const long long LIMIT = 1000000000LL; // 10^9 should be enough

    // For each palindrome, count ways to write it as a^2 + b^3
    // We'll generate palindromes and check each

    vector<long long> results;

    // Generate palindromes in order by iterating through possible values
    // Instead, iterate all numbers and check palindrome + count
    // More efficient: generate palindromes directly

    // Generate palindromes by building from half
    vector<long long> palindromes;

    // Single digit palindromes
    for (int d = 1; d <= 9; d++) palindromes.push_back(d);

    // Generate multi-digit palindromes
    for (int half_len = 1; half_len <= 5; half_len++) {
        long long start = 1;
        for (int i = 1; i < half_len; i++) start *= 10;
        long long end_ = start * 10;

        // Even length: half_len * 2
        for (long long h = start; h < end_; h++) {
            string s = to_string(h);
            string r = s;
            reverse(r.begin(), r.end());
            long long p = stoll(s + r);
            if (p < LIMIT) palindromes.push_back(p);
        }

        // Odd length: half_len + 1 + half_len - but we handle it as:
        // left half (half_len digits) + middle digit + reversed left half
        // Actually simpler: for odd length 2*half_len+1
        for (long long h = start; h < end_; h++) {
            string s = to_string(h);
            string r = s.substr(0, s.size() - 1);
            reverse(r.begin(), r.end());
            long long p = stoll(s + r);
            if (p < LIMIT) palindromes.push_back(p);
        }
    }

    sort(palindromes.begin(), palindromes.end());
    palindromes.erase(unique(palindromes.begin(), palindromes.end()), palindromes.end());

    for (long long pal : palindromes) {
        if (pal < 2) continue; // need a>=1, b>=1, so min is 1+1=2
        int count = 0;
        for (long long b = 1; b * b * b < pal; b++) {
            long long rem = pal - b * b * b;
            long long a = (long long)round(sqrt((double)rem));
            if (a >= 1 && a * a == rem) {
                count++;
            }
        }
        if (count == 4) {
            results.push_back(pal);
            if (results.size() == 5) break;
        }
    }

    long long sum = 0;
    for (long long v : results) sum += v;
    cout << sum << endl;

    return 0;
}