Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

Complete solutions in C++, Python & Java — with step-by-step mathematical explanations

All Problems

Problem 661: A Long Chess Match

View on Project Euler

Project Euler Problem 661 Solution

EulerSolve provides an optimized solution for Project Euler Problem 661, A Long Chess Match, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary The three implementations reduce the chess match to a one-dimensional lead process. If the current lead of player A is \(i\), then after one round it becomes \(i+1\) with probability \(a\), \(i-1\) with probability \(b\), and stays at \(i\) with probability \(1-a-b\). Independently, the process survives to the next round with probability \(q=1-t\), where \(t\) is the stopping probability. For each integer \(k\in\{3,4,\dots,50\}\), the parameters are $a_k=\frac{1}{\sqrt{k+3}},\qquad b_k=a_k+\frac{1}{k^2},\qquad t_k=\frac{1}{k^3},\qquad q_k=1-t_k.$ The task is to evaluate the expected lead-counting quantity attached to this stopped walk for every \(k\), and then sum those \(48\) values. The implementations do not simulate long matches; instead they solve one closed-form recurrence and reuse it for every parameter set. Mathematical Approach The cleanest derivation introduces an auxiliary state value \(U_i\), where \(i\in\mathbb Z\) is the current lead of player A. After solving for \(U_0\), the quantity printed by the implementations is obtained by dividing by \(q\). Step 1: Set Up the Auxiliary Recurrence Let \(U_i\) satisfy $U_i=\mathbf{1}_{i>0}+q\left(a\,U_{i+1}+b\,U_{i-1}+(1-a-b)U_i\right).$ The indicator term contributes one unit exactly when the current lead is positive....

Detailed mathematical approach

Problem Summary

The three implementations reduce the chess match to a one-dimensional lead process. If the current lead of player A is \(i\), then after one round it becomes \(i+1\) with probability \(a\), \(i-1\) with probability \(b\), and stays at \(i\) with probability \(1-a-b\). Independently, the process survives to the next round with probability \(q=1-t\), where \(t\) is the stopping probability.

For each integer \(k\in\{3,4,\dots,50\}\), the parameters are

$a_k=\frac{1}{\sqrt{k+3}},\qquad b_k=a_k+\frac{1}{k^2},\qquad t_k=\frac{1}{k^3},\qquad q_k=1-t_k.$

The task is to evaluate the expected lead-counting quantity attached to this stopped walk for every \(k\), and then sum those \(48\) values. The implementations do not simulate long matches; instead they solve one closed-form recurrence and reuse it for every parameter set.

Mathematical Approach

The cleanest derivation introduces an auxiliary state value \(U_i\), where \(i\in\mathbb Z\) is the current lead of player A. After solving for \(U_0\), the quantity printed by the implementations is obtained by dividing by \(q\).

Step 1: Set Up the Auxiliary Recurrence

Let \(U_i\) satisfy

$U_i=\mathbf{1}_{i>0}+q\left(a\,U_{i+1}+b\,U_{i-1}+(1-a-b)U_i\right).$

The indicator term contributes one unit exactly when the current lead is positive. This auxiliary normalization is convenient because the same linear operator appears on both sides of zero, and the final quantity of interest will simply be

$H(a,b,t)=\frac{U_0}{q}.$

Write

$s=1-a-b,\qquad c=1-q s=t+q(a+b).$

Then the recurrence becomes

$q a\,U_{i+1}-c\,U_i+q b\,U_{i-1}=-\mathbf{1}_{i>0}.$

The right-hand side is \(0\) for \(i\le 0\) and \(-1\) for \(i\ge 1\), so the problem naturally splits into a non-positive side and a positive side.

Step 2: Solve the Characteristic Equation

The homogeneous recurrence is

$q a\,U_{i+1}-c\,U_i+q b\,U_{i-1}=0.$

Substituting \(U_i=r^i\) gives the characteristic polynomial

$q a r^2-c r+q b=0.$

Its two roots are

$\rho_{\pm}=\frac{c\pm\sqrt{c^2-4q^2ab}}{2qa}.$

The discriminant is always positive in this problem family, because

$c^2-4q^2ab=\left(t+q(a+b)\right)^2-4q^2ab=t^2+2tq(a+b)+q^2(a-b)^2>0.$

So the roots are real and distinct. Moreover, evaluating the polynomial at \(r=1\) gives

$q a-c+q b=-t<0,$

while at \(r=0\) it equals \(q b>0\). Hence one root lies in \((0,1)\). Since

$\rho_-\rho_+=\frac{b}{a}>1$

for the actual parameters \(b=a+1/k^2\), the other root must be larger than \(1\). Therefore

$0<\rho_-<1<\rho_+.$

Step 3: Build the Bounded Solutions on Both Sides

For \(i\le 0\), the recurrence is homogeneous, so boundedness as \(i\to-\infty\) forces the solution to use only the root larger than \(1\):

$U_i=A\,\rho_+^i\qquad (i\le 0).$

For \(i\ge 1\), the forcing term is constant. A constant particular solution \(U_i\equiv K\) must satisfy

$K=1+qK,$

so

$K=\frac{1}{t}.$

To keep the positive side bounded as \(i\to+\infty\), we keep only the decaying root \(\rho_-\):

$U_i=\frac{1}{t}+B\,\rho_-^i\qquad (i\ge 1).$

This is the core structural simplification: one exponential branch on the left, one constant-plus-exponential branch on the right.

Step 4: Match the Boundary at \(0\) and \(1\)

We now impose the recurrence at the two interface points. At \(i=0\), substituting \(U_0=A\), \(U_{-1}=A/\rho_+\), and \(U_1=1/t+B\rho_-\) gives

$A=q\left(a\left(\frac{1}{t}+B\rho_-\right)+b\frac{A}{\rho_+}+sA\right).$

Using the characteristic equation to simplify the coefficients yields

$A\rho_+=\frac{1}{t}+B\rho_-.$

At \(i=1\), substituting \(U_1=1/t+B\rho_-\), \(U_2=1/t+B\rho_-^2\), and \(U_0=A\) gives

$\frac{1}{t}+B\rho_-=1+q\left(a\left(\frac{1}{t}+B\rho_-^2\right)+bA+s\left(\frac{1}{t}+B\rho_-\right)\right).$

After subtracting the constant particular solution and simplifying again with the characteristic equation, this reduces to

$B=A-\frac{1}{t}.$

Substituting that relation back into the previous equation gives

$A(\rho_+-\rho_-)=\frac{1-\rho_-}{t},$

so

$A=\frac{1-\rho_-}{t(\rho_+-\rho_-)}.$

Step 5: Recover the Closed Form and Sum Over \(k\)

Since the required value is \(H(a,b,t)=U_0/q=A/q\), we obtain the exact expression used by all three implementations:

$\boxed{H(a,b,t)=\frac{1-\rho_-}{tq(\rho_+-\rho_-)}}$

with

$\rho_{\pm}=\frac{c\pm\sqrt{c^2-4q^2ab}}{2qa},\qquad c=t+q(a+b),\qquad q=1-t.$

The final answer for the problem is therefore

$\sum_{k=3}^{50} H\left(\frac{1}{\sqrt{k+3}},\ \frac{1}{\sqrt{k+3}}+\frac{1}{k^2},\ \frac{1}{k^3}\right).$

That turns a potentially enormous stochastic process into a short deterministic computation: one square root and a few arithmetic operations per value of \(k\).

Worked Example: \(a=b=\frac14,\ t=\frac12\)

This exact checkpoint is especially useful because the algebra collapses nicely. Here

$q=\frac12,\qquad c=t+q(a+b)=\frac12+\frac12\cdot\frac12=\frac34.$

The discriminant is

$c^2-4q^2ab=\frac{9}{16}-4\cdot\frac14\cdot\frac1{16}=\frac12,$

so the two roots are

$\rho_-=\frac{\frac34-\sqrt{\frac12}}{\frac14}=3-2\sqrt2,\qquad \rho_+=3+2\sqrt2.$

Then

$\rho_+-\rho_-=4\sqrt2,\qquad 1-\rho_-=2(\sqrt2-1).$

Plugging these into the closed form gives

$H\left(\frac14,\frac14,\frac12\right)=\frac{2(\sqrt2-1)}{\frac12\cdot\frac12\cdot 4\sqrt2}=2-\sqrt2\approx 0.585786.$

This matches the numerical checkpoint embedded in the implementations. For the actual parameter family, the first term of the final sum, corresponding to \(k=3\), is approximately \(6.8345\).

How the Code Works

The C++, Python, and Java implementations all follow exactly the same mathematical pipeline. For each \(k\) from \(3\) to \(50\), they construct \(a_k\), \(b_k\), and \(t_k\); compute \(q_k\), \(c_k\), the discriminant, and the square root; form the smaller and larger characteristic roots; and then evaluate the closed form above.

No dynamic programming table, recursion tree, or Monte Carlo sampling is needed. The entire match model has already been collapsed into the algebraic expression for \(H(a,b,t)\), so each loop iteration is independent and constant size.

The language-specific difference is numerical precision rather than algorithm design. The C++ version uses extended floating-point arithmetic, the Python version uses decimal arithmetic with high precision, and the Java version uses decimal arithmetic with a high-precision math context. All three then accumulate the \(48\) terms and format the final total to four decimal places.

Complexity Analysis

The loop runs for exactly \(48\) values of \(k\). Each iteration performs a fixed number of arithmetic operations and one square root, so for fixed precision the running time is \(O(1)\) overall and the memory usage is \(O(1)\).

If one wants to count the cost of arbitrary-precision arithmetic explicitly, then the dominant operation is still the square root in each iteration, but the precision level is fixed by the required decimal output. In practice the computation is tiny.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=661
  2. Random walk: Wikipedia - Random walk
  3. Birth-death process: Wikipedia - Birth-death process
  4. Geometric distribution: Wikipedia - Geometric distribution
  5. Linear recurrence with constant coefficients: Wikipedia - Linear recurrence with constant coefficients

Mathematical approach · C++ solution · Python solution · Java solution

Previous: Problem 660 · All Project Euler solutions · Next: Problem 662

Need help with a problem? Ask me! 💡
e
✦ Euler GLM 5.2
Hi! I'm Euler. Ask me anything about Project Euler problems, math concepts, or solution approaches! 🧮