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 Apr 19, 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 (dkdk1d1d0)b(d_k d_{k-1} \cdots d_1 d_0)_b (where dk0d_k \neq 0) is a palindrome if di=dkid_i = d_{k-i} for all 0ik0 \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)=(b1)b(k1)/2C_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 b1b-1 choices (nonzero), and the remaining k/21\lceil k/2 \rceil - 1 digits each have bb choices. Thus:

Cb(k)=(b1)bk/21=(b1)b(k1)/2C_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)=(b1)k=1Kb(k1)/2P_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)=2j=0K/21(b1)bj+ϵ=2(bK/21)+ϵ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=logbN+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=1K1Cb(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(b1)b(k1)/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(k1)/2)(d_0, d_1, \ldots, d_{\lfloor(k-1)/2\rfloor}) with d0{1,,b1}d_0 \in \{1, \ldots, b-1\} and di{0,,b1}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(k1)/2di(bk1i+bi)[k odd]dk/2bk/2n = \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(logbN)O(\log_b N)O(logbN)O(\log_b N)
Enumerate all palindromes N\leq NO(Pb(N))O(P_b(N))O(logbN)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 NbkN \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;
}