Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 301: Nim

View on Project Euler

Project Euler Problem 301 Solution

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

Problem Summary The title refers to a three-heap Nim position with heap sizes $n,\qquad 2n,\qquad 3n.$ In Nim, a position is losing for the next player exactly when the xor of the heap sizes is zero. So we must count the integers \(n\) with $1\le n\le 2^k,\qquad n\oplus 2n\oplus 3n=0.$ Mathematical Approach 1. Convert the Nim condition into a carry condition Since $3n=n+2n,$ the xor condition becomes $n\oplus 2n\oplus (n+2n)=0.$ Now recall the binary identity $a\oplus b=a+b \iff a\land b=0,$ which says that xor equals ordinary addition exactly when no carry occurs. Therefore $n\oplus 2n\oplus 3n=0 \iff n\oplus 2n = n+2n \iff n\land 2n = 0.$ So the whole problem is reduced to asking when the binary expansions of \(n\) and \(2n\) overlap. 2. Why this means “no adjacent 1-bits” Multiplying by \(2\) is just a left shift: $2n = n \ll 1.$ Thus the bitwise condition $n\land 2n = 0$ means that no 1-bit of \(n\) may sit immediately next to another 1-bit, because a bit at position \(i\) in \(n\) overlaps with a bit at position \(i+1\) after shifting. Hence $n\oplus 2n\oplus 3n=0$ if and only if the binary representation of \(n\) contains no substring \(11\). 3. Small example Take \(n=5\)....

Detailed mathematical approach

Problem Summary

The title refers to a three-heap Nim position with heap sizes

$n,\qquad 2n,\qquad 3n.$

In Nim, a position is losing for the next player exactly when the xor of the heap sizes is zero. So we must count the integers \(n\) with

$1\le n\le 2^k,\qquad n\oplus 2n\oplus 3n=0.$

Mathematical Approach

1. Convert the Nim condition into a carry condition

Since

$3n=n+2n,$

the xor condition becomes

$n\oplus 2n\oplus (n+2n)=0.$

Now recall the binary identity

$a\oplus b=a+b \iff a\land b=0,$

which says that xor equals ordinary addition exactly when no carry occurs. Therefore

$n\oplus 2n\oplus 3n=0 \iff n\oplus 2n = n+2n \iff n\land 2n = 0.$

So the whole problem is reduced to asking when the binary expansions of \(n\) and \(2n\) overlap.

2. Why this means “no adjacent 1-bits”

Multiplying by \(2\) is just a left shift:

$2n = n \ll 1.$

Thus the bitwise condition

$n\land 2n = 0$

means that no 1-bit of \(n\) may sit immediately next to another 1-bit, because a bit at position \(i\) in \(n\) overlaps with a bit at position \(i+1\) after shifting. Hence

$n\oplus 2n\oplus 3n=0$

if and only if the binary representation of \(n\) contains no substring \(11\).

3. Small example

Take \(n=5\). In binary,

$5=101_2,\qquad 10=1010_2,\qquad 15=1111_2.$

Because \(101\) has no adjacent 1s, the carry-free condition holds, and indeed

$5\oplus 10\oplus 15=0.$

Now take \(n=6\):

$6=110_2.$

This contains adjacent 1s, so \(6+12\) has a carry, and correspondingly

$6\oplus 12\oplus 18\ne 0.$

4. Counting binary strings with no consecutive ones

Let \(A_t\) be the number of binary strings of length \(t\) with no adjacent 1s. There are two cases:

Ending in 0. Then the first \(t-1\) bits form any valid length-\((t-1)\) string.

Ending in 1. Then the previous bit must be 0, and the first \(t-2\) bits form any valid length-\((t-2)\) string.

Therefore

$A_t=A_{t-1}+A_{t-2},$

with initial values

$A_0=1,\qquad A_1=2.$

So \(A_t\) is a Fibonacci count. If we use the convention

$F_1=1,\qquad F_2=1,\qquad F_{m}=F_{m-1}+F_{m-2},$

then

$A_t=F_{t+2}.$

5. Why the answer for \([1,2^k]\) is still one Fibonacci number

The count \(A_k\) describes valid \(k\)-bit strings, which is the same as valid integers in the half-open range

$0\le n<2^k.$

But the problem asks for

$1\le n\le 2^k.$

This changes the set in a very simple way: we remove \(0\), but we add \(2^k\), whose binary form is

$1000\cdots 0,$

and that number is also valid because it clearly has no adjacent 1s. So the count does not change at all. Hence the final answer is

$A_k=F_{k+2}.$

The implementation sets bits = exponent + 1 and returns the corresponding Fibonacci entry, which is exactly this value.

6. Checkpoints

For \(k=3\), the valid values are

$1,2,4,5,8,$

so the count is

$5=F_5.$

For the C++ checkpoint,

$k=10 \Rightarrow F_{12}=144.$

For the actual Project Euler target,

$k=30 \Rightarrow F_{32}=2178309.$

How the Code Works

The solver does not test any \(n\) individually. It simply builds Fibonacci numbers up to index \(k+2\) and returns that value. The brute-force checks in the C++ version for small exponents confirm that this combinatorial count exactly matches the xor definition.

Complexity Analysis

The runtime is

$O(k),$

and memory is also \(O(k)\) in the current implementation, though it could be reduced to \(O(1)\) with two rolling Fibonacci variables. This is exponentially better than checking all \(2^k\) candidates.

Further Reading

  1. Problem page: https://projecteuler.net/problem=301
  2. Nim and xor: https://en.wikipedia.org/wiki/Nim
  3. Fibonacci counting of binary strings: https://en.wikipedia.org/wiki/Fibonacci_number

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

Previous: Problem 300 · All Project Euler solutions · Next: Problem 302

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