All Euler problems
Project Euler

The Race

Two players alternate turns in a race to 100 points (Player 1 goes first). Player 1's turn: Flip one fair coin. Heads scores 1 point; tails scores nothing. Player 2's turn: Choose a positive intege...

Source sync Apr 19, 2026
Problem #0232
Level Level 10
Solved By 2,079
Languages C++, Python
Answer 0.83648556
Length 821 words
probabilitylinear_algebragame_theory

Problem Statement

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

Two players share an unbiased coin and take it in turns to play The Race.

On Player 1’s turn, the coin is tossed once. If it comes up Heads, then Player 1 scores one point; if it comes up Tails, then no points are scored.

On Player 2’s turn, a positive integer, \(T\), is chosen by Player 2 and the coin is tossed \(T\) times. If it comes up all Heads, then Player 2 scores \(2^{T-1}\) points; otherwise, no points are scored.

Player 1 goes first and the winner is the first to 100 or more points.

Player 2 will always select the number, \(T\), of coin tosses that maximises the probability of winning.

What is the probability that Player 2 wins?

Give your answer rounded to eight decimal places in the form \(0.abcdefgh\).

Problem 232: The Race

Mathematical Foundation

Theorem (Optimal Strategy Characterization). Define:

  • P(a,b)P(a, b): probability Player 2 wins when it is Player 2’s turn, Player 1 needs aa more points, Player 2 needs bb more points.
  • Q(a,b)Q(a, b): probability Player 2 wins when it is Player 1’s turn with the same state.

Then PP and QQ satisfy the coupled recurrences:

Q(a,b)=12P(a1,b)+12P(a,b)Q(a, b) = \frac{1}{2} P(a-1, b) + \frac{1}{2} P(a, b) P(a,b)=maxT1[12TW(T)+(112T)Q(a,b)]P(a, b) = \max_{T \geq 1} \left[ \frac{1}{2^T} W(T) + \left(1 - \frac{1}{2^T}\right) Q(a, b) \right]

where W(T)=Q(a,max(b2T1,0))W(T) = Q(a, \max(b - 2^{T-1}, 0)) if b>2T1b > 2^{T-1}, and W(T)=1W(T) = 1 if b2T1b \leq 2^{T-1}.

Proof. On Player 1’s turn, the coin is fair, so with probability 1/21/2 Player 1 scores (reducing their deficit to a1a-1) and with probability 1/21/2 scores nothing. In either case, it becomes Player 2’s turn, giving Q(a,b)=12P(a1,b)+12P(a,b)Q(a,b) = \frac{1}{2}P(a-1,b) + \frac{1}{2}P(a,b). On Player 2’s turn, choosing TT yields success probability 1/2T1/2^T for 2T12^{T-1} points and failure probability 11/2T1 - 1/2^T returning to Player 1’s turn. Player 2 maximizes over TT, establishing the recurrence for PP. \square

Lemma (Elimination of QQ). Substituting the expression for QQ into PP and solving algebraically yields

P(a,b)=maxT12pTW(T)+(1pT)P(a1,b)1+pTP(a, b) = \max_{T \geq 1} \frac{2 p_T \cdot W(T) + (1 - p_T) \cdot P(a-1, b)}{1 + p_T}

where pT=1/2Tp_T = 1/2^T.

Proof. Substituting Q(a,b)=12P(a1,b)+12P(a,b)Q(a,b) = \frac{1}{2}P(a-1,b) + \frac{1}{2}P(a,b) into P(a,b)=pTW(T)+(1pT)Q(a,b)P(a,b) = p_T W(T) + (1-p_T)Q(a,b) gives P(a,b)=pTW(T)+(1pT)[12P(a1,b)+12P(a,b)]P(a,b) = p_T W(T) + (1-p_T)[\frac{1}{2}P(a-1,b) + \frac{1}{2}P(a,b)]. Collecting P(a,b)P(a,b) on the left: P(a,b)[1(1pT)/2]=pTW(T)+(1pT)P(a1,b)/2P(a,b)[1 - (1-p_T)/2] = p_T W(T) + (1-p_T)P(a-1,b)/2. Since 1(1pT)/2=(1+pT)/21 - (1-p_T)/2 = (1+p_T)/2, solving gives the stated formula. \square

Editorial

Two players alternate turns (Player 1 first). First to 100 or more wins. Player 2 chooses T optimally each turn. Find probability Player 2 wins, to 8 decimal places. State: after Player 1’s turn, (a, b) where a = points P1 still needs, b = points P2 still needs. If a <= 0 after P1’s turn, P1 wins immediately. Let P(a, b) = prob P2 wins when it’s P2’s turn, P1 needs a, P2 needs b. Let Q(a, b) = prob P2 wins when it’s P1’s turn, P1 needs a, P2 needs b. Q(a, b) = 1/2 * P(a-1, b) + 1/2 * P(a, b) [P1 scores or not] But if a-1 <= 0, P1 wins: P(0, b) = 0 for b > 0. P(a, 0) = 1 for a > 0 (P2 already won… but P2 hasn’t played yet when we enter Q, actually if b <= 0, P2 already won on a previous turn). Wait, let me redefine more carefully. Q(a, b) = prob P2 wins, it’s start of a round (P1’s turn), P1 needs a, P2 needs b. If a <= 0: impossible (game would have ended). If b <= 0: P2 already won, so Q(a, b) = 1. But this shouldn’t happen either. Actually: Q(a,b) for a >= 1, b >= 1. Q(a, b) = 1/2 * P(a-1, b) + 1/2 * P(a, b) P(a, b) = prob P2 wins, it’s P2’s turn, P1 needs a, P2 needs b. If a <= 0: P1 already reached 100 on their turn -> P1 wins -> P(a, b) = 0 for a <= 0, b > 0. If a > 0, b <= 0: impossible (means P2 already won previously). For a >= 1, b >= 1: P(a, b) = max over T >= 1 of: (1/2^T) * Q(a, max(b - 2^(T-1), 0) if b - 2^(T-1) > 0 else -> P2 wins = 1) + (1 - 1/2^T) * Q(a, b) If P2 scores and reaches 100+: P2 wins immediately, prob = 1. So: if b <= 2^(T-1): the scoring outcome means P2 wins. P(a, b) = max_T [ (1/2^T) * win_val + (1 - 1/2^T) * Q(a, b) ] where win_val = Q(a, b - 2^(T-1)) if b > 2^(T-1), else 1. We want Q(100, 100). Bottom-up: We need Q(a, b) for a from 1..100, b from 1..100. Q depends on P(a-1, b) and P(a, b). P(0, b) = 0. P(a, b) depends on Q(a, b’) for b’ < b and Q(a, b). P(a, b) = max_T [ (1/2^T) * win_val(T) + (1 - 1/2^T) * Q(a, b) ] And Q(a, b) = 1/2 * P(a-1, b) + 1/2 * P(a, b) Substituting Q into P: P(a,b) = max_T [ (1/2^T)W(T) + (1-1/2^T)(1/2P(a-1,b) + 1/2P(a,b)) ] Let pt = 1/2^T P(a,b) = max_T [ ptW + (1-pt)/2P(a-1,b) + (1-pt)/2P(a,b) ] P(a,b) - (1-pt)/2 * P(a,b) = ptW + (1-pt)/2P(a-1,b) P(a,b) * [1 - (1-pt)/2] = ptW + (1-pt)/2P(a-1,b) P(a,b) * [(1+pt)/2] = ptW + (1-pt)/2P(a-1,b) P(a,b) = [2ptW + (1-pt)P(a-1,b)] / (1+pt) where W = Q(a, b - 2^(T-1)) if b > 2^(T-1), else 1 and Q(a, b’) = 1/2P(a-1,b’) + 1/2P(a,b’) So we iterate a from 1 to 100, b from 1 to 100. P(a, b) depends on P(a-1, b) and Q(a, b’) for b’ < b. Q(a, b’) = 1/2P(a-1, b’) + 1/2P(a, b’) — both already computed. We boundary: P(0, b) = 0 for b > 0; Q(a, 0) = 1 for a > 0. We then else. Finally, but P[a][b - 2^(T-1)] is already computed since b - 2^(T-1) < b.

Pseudocode

Boundary: P(0, b) = 0 for b > 0; Q(a, 0) = 1 for a > 0
else
But P[a][b - 2^(T-1)] is already computed since b - 2^(T-1) < b
Answer: Q(100, 100) = 0.5 * P[99][100] + 0.5 * P[100][100]

Complexity Analysis

  • Time: O(N2logN)O(N^2 \log N) where N=100N = 100. For each of N2N^2 states, we try O(logN)O(\log N) values of TT.
  • Space: O(N2)O(N^2) for the DP table.

Answer

0.83648556\boxed{0.83648556}

Code

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

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

int main() {
    const int N = 100;

    // P[a][b] = prob P2 wins when it's P2's turn, P1 needs a, P2 needs b
    // Q[a][b] = prob P2 wins when it's P1's turn
    vector<vector<double>> P(N + 1, vector<double>(N + 1, 0.0));
    vector<vector<double>> Q(N + 1, vector<double>(N + 1, 0.0));

    // Boundaries
    // P[0][b] = 0 (P1 reached 100)
    // Q[a][0] = 1 for a > 0 (P2 already won)
    for (int a = 1; a <= N; a++) {
        Q[a][0] = 1.0;
        P[a][0] = 1.0;
    }

    for (int a = 1; a <= N; a++) {
        for (int b = 1; b <= N; b++) {
            // P(a,b) = max_T [2*pt*W + (1-pt)*P(a-1,b)] / (1+pt)
            // where pt = 1/2^T, score = 2^(T-1)
            double best = 0.0;
            int score = 1;
            for (int T = 1; T < 40; T++) {
                double pt = pow(0.5, T);
                double W;
                if (b > score) {
                    W = Q[a][b - score];
                } else {
                    W = 1.0; // P2 wins
                }
                double val = (2.0 * pt * W + (1.0 - pt) * P[a - 1][b]) / (1.0 + pt);
                if (val > best) best = val;
                if (score >= N) break;
                score *= 2;
            }
            P[a][b] = best;
            Q[a][b] = 0.5 * P[a - 1][b] + 0.5 * P[a][b];
        }
    }

    printf("%.8f\n", Q[N][N]);
    return 0;
}