All Euler problems
Project Euler

Base-b Palindromes

A number n is a palindrome in base b if its base- b representation reads the same forwards and backwards. Let P_b(N) count the number of positive integers <= N that are palindromic in base b. Given...

Source sync May 21, 2026
Problem #0897
Level Level 24
Solved By 472
Languages C++, Python
Answer 1.599827123
Length 493 words
linear_algebramodular_arithmeticbrute_force

Problem Statement

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

Let \(G(n)\) denote the largest possible area of an \(n\)-gon contained in the region \(\{(x, y) \in \Bbb R^2: x^4 \leq y \leq 1\}\). For example, \(G(3) = 1\) and \(G(5)\approx 1.477309771\).

Find \(G(101)\) rounded to nine digits after the decimal point.

Problem 897: Base-b Palindromes

Mathematical Analysis

Definition

A positive integer nn with base-bb representation (dkdk−1⋯d1d0)b(d_k d_{k-1} \cdots d_1 d_0)_b (where dk≠0d_k \neq 0) is a palindrome if di=dk−id_i = d_{k-i} for all 0≤i≤k0 \leq i \leq k.

Theorem 1 (Counting kk-digit Palindromes in Base bb)

The number of kk-digit palindromes in base bb is:

Cb(k)=(b−1)⋅b⌊(k−1)/2⌋C_b(k) = (b-1) \cdot b^{\lfloor(k-1)/2\rfloor}

Proof. A kk-digit palindrome is determined by its first ⌈k/2⌉\lceil k/2 \rceil digits. The leading digit has b−1b-1 choices (nonzero), and the remaining ⌈k/2⌉−1\lceil k/2 \rceil - 1 digits each have bb choices. Thus:

Cb(k)=(b−1)⋅b⌈k/2⌉−1=(b−1)⋅b⌊(k−1)/2⌋□C_b(k) = (b-1) \cdot b^{\lceil k/2 \rceil - 1} = (b-1) \cdot b^{\lfloor(k-1)/2\rfloor} \qquad \square

Theorem 2 (Total Palindromes with at Most KK digits)

Pb(≤K)=∑k=1KCb(k)=(b−1)∑k=1Kb⌊(k−1)/2⌋P_b^{(\leq K)} = \sum_{k=1}^{K} C_b(k) = (b-1)\sum_{k=1}^{K} b^{\lfloor(k-1)/2\rfloor}

Splitting into odd and even kk:

Pb(≤K)=2∑j=0⌊K/2⌋−1(b−1)bj+ϵ=2(b⌊K/2⌋−1)+ϵP_b^{(\leq K)} = 2\sum_{j=0}^{\lfloor K/2 \rfloor - 1} (b-1) b^j + \epsilon = 2(b^{\lfloor K/2 \rfloor} - 1) + \epsilon

where ϵ\epsilon accounts for the parity of KK.

Theorem 3 (Palindromes up to NN in Base bb)

Let K=⌊log⁡bN⌋+1K = \lfloor \log_b N \rfloor + 1 be the number of digits of NN in base bb.

  1. Count all palindromes with fewer than KK digits: ∑k=1K−1Cb(k)\sum_{k=1}^{K-1} C_b(k).
  2. Count KK-digit palindromes ≤N\leq N: enumerate the first ⌈K/2⌉\lceil K/2 \rceil digits such that the resulting palindrome is ≤N\leq N.

Concrete Numerical Examples

Base 10 Palindromes

DigitsCountExamples
191, 2, …, 9
2911, 22, …, 99
390101, 111, …, 999
4901001, 1111, …, 9999
590010001, …, 99999

Total ≤999\leq 999: 9+9+90=1089 + 9 + 90 = 108.

Base 2 Palindromes ≤31\leq 31

nnBinaryPalindrome?
11Yes
311Yes
5101Yes
7111Yes
91001Yes
151111Yes
2110101Yes
2711011Yes
3111111Yes

P2(31)=9P_2(31) = 9.

Multi-base Palindromes

Numbers that are palindromes in both base 2 and base 10 (first few): 1,3,5,7,9,33,99,585,717,…1, 3, 5, 7, 9, 33, 99, 585, 717, \ldots

Verification Table: Cb(k)C_b(k) Formula

bbkk(b−1)⋅b⌊(k−1)/2⌋(b-1) \cdot b^{\lfloor(k-1)/2\rfloor}Direct countMatch
10199Yes
10299Yes
1039090Yes
2111Yes
2322Yes
2544Yes
3122Yes
3222Yes
3366Yes

Generating Palindromes

To enumerate all kk-digit base-bb palindromes: iterate over the “half” (d0,d1,…,d⌊(k−1)/2⌋)(d_0, d_1, \ldots, d_{\lfloor(k-1)/2\rfloor}) with d0∈{1,…,b−1}d_0 \in \{1, \ldots, b-1\} and di∈{0,…,b−1}d_i \in \{0, \ldots, b-1\}, then mirror.

Value of palindrome: For a kk-digit palindrome with half-digits (d0,d1,…)(d_0, d_1, \ldots):

n=∑i=0⌊(k−1)/2⌋di(bk−1−i+bi)−[k odd]⋅d⌊k/2⌋⋅b⌊k/2⌋n = \sum_{i=0}^{\lfloor(k-1)/2\rfloor} d_i \left(b^{k-1-i} + b^i\right) - [k \text{ odd}] \cdot d_{\lfloor k/2 \rfloor} \cdot b^{\lfloor k/2 \rfloor}

(subtracting the middle digit’s double count when kk is odd).

Complexity Analysis

OperationTimeSpace
Count palindromes with ≤K\leq K digitsO(K)O(K)O(1)O(1)
Count palindromes ≤N\leq NO(log⁡bN)O(\log_b N)O(log⁡bN)O(\log_b N)
Enumerate all palindromes ≤N\leq NO(Pb(N))O(P_b(N))O(log⁡bN)O(\log_b N)

Since Pb(N)=O(N)P_b(N) = O(\sqrt{N}) (palindromes of kk digits number O(bk/2)O(b^{k/2}) and N≈bkN \approx b^k), palindrome enumeration is sublinear.

Answer

1.599827123\boxed{1.599827123}

Code

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

C++ project_euler/problem_897/solution.cpp
/*
 * Problem 897: Base-b Palindromes
 * Count palindromic numbers in base b up to N.
 * Key formula: C_b(k) = (b-1) * b^(floor((k-1)/2)) for k-digit palindromes.
 * Total palindromes up to N is O(sqrt(N)).
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

vector<int> to_base(ll n, int b) {
    if (n == 0) return {0};
    vector<int> digits;
    while (n > 0) { digits.push_back(n % b); n /= b; }
    reverse(digits.begin(), digits.end());
    return digits;
}

bool is_palindrome(ll n, int b) {
    auto d = to_base(n, b);
    int sz = d.size();
    for (int i = 0; i < sz / 2; i++)
        if (d[i] != d[sz - 1 - i]) return false;
    return true;
}

ll count_k_digit(int k, int b) {
    // (b-1) * b^(floor((k-1)/2))
    ll result = b - 1;
    for (int i = 0; i < (k - 1) / 2; i++) result *= b;
    return result;
}

ll count_up_to_brute(ll N, int b) {
    ll count = 0;
    for (ll n = 1; n <= N; n++)
        if (is_palindrome(n, b)) count++;
    return count;
}

// Generate all base-b palindromes up to max_val
vector<ll> generate_palindromes(ll max_val, int b) {
    vector<ll> pals;
    for (int k = 1; k <= 40; k++) {
        int half = (k + 1) / 2;
        ll start = (half == 1) ? 1 : 1;
        // iterate over first-half values
        ll lo = 1;
        for (int i = 1; i < half; i++) lo *= b;
        ll hi = lo * b;
        for (ll h = lo; h < hi; h++) {
            auto hd = to_base(h, b);
            // build palindrome
            vector<int> pd = hd;
            if (k % 2 == 0) {
                for (int i = hd.size() - 1; i >= 0; i--) pd.push_back(hd[i]);
            } else {
                for (int i = (int)hd.size() - 2; i >= 0; i--) pd.push_back(hd[i]);
            }
            ll val = 0;
            for (int d : pd) val = val * b + d;
            if (val > max_val) return pals;
            pals.push_back(val);
        }
    }
    return pals;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    // Verify C_b(k) formula
    cout << "=== C_b(k) Verification ===" << endl;
    for (int b : {2, 3, 10}) {
        for (int k = 1; k <= 4; k++) {
            ll formula = count_k_digit(k, b);
            ll lo = 1;
            for (int i = 1; i < k; i++) lo *= b;
            ll hi = lo * b - 1;
            if (k == 1) lo = 1;
            ll direct = 0;
            for (ll n = lo; n <= hi && n <= 100000; n++)
                if (is_palindrome(n, b)) direct++;
            cout << "b=" << b << " k=" << k << ": formula=" << formula
                 << " direct=" << direct
                 << (formula == direct ? " OK" : " FAIL") << endl;
        }
    }

    // Count palindromes up to N
    cout << "\n=== Palindrome Counts ===" << endl;
    for (int b : {2, 10}) {
        for (ll N : {100LL, 1000LL, 10000LL}) {
            ll cnt = count_up_to_brute(N, b);
            cout << "P_" << b << "(" << N << ") = " << cnt << endl;
        }
    }

    // Generate and count
    auto pals = generate_palindromes(1000000, 10);
    cout << "\nP_10(10^6) = " << pals.size() << endl;

    cout << "\nAnswer: " << pals.size() << endl;
    return 0;
}