Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 824: Chess Sliders

View on Project Euler

Project Euler Problem 824 Solution

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

Problem Summary The Chess Sliders problem leads to a counting function \(L(N,K)\). For the required parameters \(N=10^9\) and \(K=10^{15}\), a direct combinatorial enumeration is hopeless, so the goal is to evaluate the answer modulo \(p^2\) with $p=10{,}000{,}019.$ The implementations show that the practical route is to replace the original counting problem by a finite alternating sum, then evaluate each summand through coefficient extraction and p-adic binomial arithmetic. Mathematical Approach The formula used by the implementations is $L(N,K)=\sum_{j=0}^{J}(-1)^{Nj}\binom{N}{j}\,c\bigl(N(N-2j),\,K-Nj\bigr)\pmod{p^2},\qquad J=\left\lfloor\frac{K}{N}\right\rfloor,$ where \(c(m,k)\) is a coefficient extracted from the algebraic series \(\lambda_+(x)\) that appears in the combinatorial derivation. The rest of the work is making this expression computable modulo \(p^2\). Step 1: Compress the counting problem into a finite sum The outer index only runs up to $J=\left\lfloor\frac{K}{N}\right\rfloor,$ because the second argument of \(c(m,k)\) is \(k=K-Nj\), which becomes negative once \(j>J\). So the chess-slider count is already reduced to a finite sum of about \(K/N\) terms rather than an exponential search over configurations....

Detailed mathematical approach

Problem Summary

The Chess Sliders problem leads to a counting function \(L(N,K)\). For the required parameters \(N=10^9\) and \(K=10^{15}\), a direct combinatorial enumeration is hopeless, so the goal is to evaluate the answer modulo \(p^2\) with

$p=10{,}000{,}019.$

The implementations show that the practical route is to replace the original counting problem by a finite alternating sum, then evaluate each summand through coefficient extraction and p-adic binomial arithmetic.

Mathematical Approach

The formula used by the implementations is

$L(N,K)=\sum_{j=0}^{J}(-1)^{Nj}\binom{N}{j}\,c\bigl(N(N-2j),\,K-Nj\bigr)\pmod{p^2},\qquad J=\left\lfloor\frac{K}{N}\right\rfloor,$

where \(c(m,k)\) is a coefficient extracted from the algebraic series \(\lambda_+(x)\) that appears in the combinatorial derivation. The rest of the work is making this expression computable modulo \(p^2\).

Step 1: Compress the counting problem into a finite sum

The outer index only runs up to

$J=\left\lfloor\frac{K}{N}\right\rfloor,$

because the second argument of \(c(m,k)\) is \(k=K-Nj\), which becomes negative once \(j>J\). So the chess-slider count is already reduced to a finite sum of about \(K/N\) terms rather than an exponential search over configurations.

For the actual input,

$J=\left\lfloor\frac{10^{15}}{10^9}\right\rfloor=10^6,$

which is large but still feasible if each term can be evaluated quickly.

Step 2: Replace the generating-function coefficient by a closed form

The implementations never expand \(\lambda_+(x)\) term by term. Instead they use Lagrange inversion, which gives, for \(k\ge 1\),

$c(m,k)=[x^k]\lambda_+(x)^m=\frac{m}{k}\binom{m-k-1}{k-1}.$

This is the key simplification: a coefficient of an algebraic series becomes a single binomial coefficient multiplied by \(m/k\). The constant-term case is handled separately:

$c(m,0)=\begin{cases} 1,&m=0,\\ 0,&m\ne 0. \end{cases}$

That boundary value is essential for the last term in small validation examples.

Step 3: Evaluate binomial coefficients modulo \(p^2\)

Now we must compute \(\binom{n}{r}\pmod{p^2}\) when \(n\) and \(r\) may be enormous. Let

$v_p(n!)=\sum_{t\ge 1}\left\lfloor\frac{n}{p^t}\right\rfloor$

be Legendre's formula. Then

$e=v_p\!\left(\binom{n}{r}\right)=v_p(n!)-v_p(r!)-v_p((n-r)!).$

If \(e\ge 2\), then the binomial coefficient is divisible by \(p^2\), so it is \(0\) modulo \(p^2\). Otherwise write

$n!=p^{v_p(n!)}\,n!_{(p)},$

where \(n!_{(p)}\) is the factorial with all factors of \(p\) removed. Since the remaining denominator is now coprime to \(p\), it is invertible modulo \(p^2\), and therefore

$\binom{n}{r}\equiv p^e\cdot\frac{n!_{(p)}}{r!_{(p)}(n-r)!_{(p)}}\pmod{p^2}.$

So the real task is to compute these p-free factorial parts efficiently.

Step 4: Recurse on the p-free factorial part

Write

$n=qp+r,\qquad 0\le r<p.$

Splitting \(1,2,\dots,n\) into complete blocks of length \(p\) and one final partial block gives the congruence

$n!_{(p)}\equiv q!_{(p)}\cdot\bigl((p-1)!\bigr)^q\cdot r!\cdot\bigl(1+qp\,H_r\bigr)\pmod{p^2},$

where

$H_r=\sum_{i=1}^{r} i^{-1}\pmod{p^2}.$

The harmonic factor comes from

$\prod_{i=1}^{r}(qp+i)=r!\prod_{i=1}^{r}\left(1+\frac{qp}{i}\right)\equiv r!\left(1+qp\sum_{i=1}^{r}\frac{1}{i}\right)\pmod{p^2}.$

Each recursive step divides the argument by \(p\), so the depth is only \(O(\log_p n)\), which is tiny here.

Step 5: Build the row \(\binom{N}{j}\) once

The alternating sum needs \(\binom{N}{j}\) for every \(0\le j\le J\). Instead of recomputing each binomial from scratch, the implementations use the recurrence

$\binom{N}{j+1}=\binom{N}{j}\cdot\frac{N-j}{j+1}\pmod{p^2}.$

For the actual input, \(J=10^6<p\), so every denominator \(j+1\) is invertible modulo \(p^2\). This turns the whole row into a linear-time precomputation.

Step 6: Assemble the final answer

For each \(j\), define

$m_j=N(N-2j),\qquad k_j=K-Nj.$

Then evaluate \(c(m_j,k_j)\) using Step 2, compute the required binomial coefficient modulo \(p^2\) via Steps 3 and 4, multiply by \(\binom{N}{j}\), apply the sign \((-1)^{Nj}\), and add the result modulo \(p^2\).

Because

$(-1)^{Nj}=\begin{cases} 1,&N\text{ is even},\\ (-1)^j,&N\text{ is odd}, \end{cases}$

the sign rule is especially cheap to evaluate.

Worked Example: \(L(2,2)\)

This is the smallest checkpoint used by the implementations. Here

$J=\left\lfloor\frac{2}{2}\right\rfloor=1,$

so there are two terms.

For \(j=0\),

$m_0=2(2-0)=4,\qquad k_0=2,\qquad \binom{2}{0}=1,$

hence

$c(4,2)=\frac{4}{2}\binom{1}{1}=2.$

The first contribution is \(1\cdot 2=2\).

For \(j=1\),

$m_1=2(2-2)=0,\qquad k_1=0,\qquad \binom{2}{1}=2.$

The boundary rule gives \(c(0,0)=1\), so the second contribution is \(2\cdot 1=2\). Since \(N\) is even, no sign change occurs. Therefore

$L(2,2)=2+2=4,$

matching the validation value.

How the Code Works

The C++, Python, and Java implementations follow the same mathematical pipeline. First they precompute factorial residues up to \(p-1\), modular inverses of the small nonzero residues, and the cumulative harmonic sums \(H_r\). Those tables are exactly what the p-free factorial recursion needs.

Next they generate the entire row \(\binom{N}{0},\binom{N}{1},\dots,\binom{N}{J}\) with the one-step recurrence from Step 5. After that they iterate over \(j=0,\dots,J\), evaluate the coefficient \(c(m_j,k_j)\), compute the associated binomial coefficient modulo \(p^2\), multiply by \(\binom{N}{j}\), apply the alternating sign, and accumulate the total.

The C++ implementation additionally splits the range of \(j\) across available hardware threads and combines the partial sums at the end. The Python and Java implementations perform the same arithmetic serially, but the underlying mathematics is identical.

Complexity Analysis

Let \(J=\lfloor K/N\rfloor\). Precomputing factorial residues, inverses, and harmonic sums up to \(p-1\) costs \(O(p)\) time and \(O(p)\) memory. Building the row \(\binom{N}{j}\) costs \(O(J)\) time and \(O(J)\) memory. Each summand then needs only \(O(\log_p K)\) p-adic recursive work, so the whole accumulation is \(O(J\log_p K)\), which is essentially linear here because \(p\approx 10^7\). The total memory usage is \(O(p+J)\), and the C++ version reduces wall-clock time further by parallelizing the outer sum.

Footnotes and References

  1. Problem page: Project Euler 824
  2. Lagrange inversion theorem: Wikipedia - Lagrange inversion theorem
  3. Legendre's formula: Wikipedia - Legendre's formula
  4. p-adic valuation: Wikipedia - p-adic valuation
  5. Harmonic number: Wikipedia - Harmonic number

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

Previous: Problem 823 · All Project Euler solutions · Next: Problem 825

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! 🧮