Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 669: The King's Banquet

View on Project Euler

Project Euler Problem 669 Solution

EulerSolve provides an optimized solution for Project Euler Problem 669, The King's Banquet, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary Let \(F_1=F_2=1\) and \(F_{j+2}=F_{j+1}+F_j\). On the vertex set \(\{1,2,\dots,n\}\), we join \(u\) and \(v\) exactly when \(u+v\) is a Fibonacci number. The problem asks for the label at a specified place in a Hamiltonian path when \(n=F_{83}\). The crucial point is that for Fibonacci-sized graphs \(n=F_k\), the path used by the implementations is not found by search; it is given by a closed arithmetic rule. Mathematical Approach For graphs of size \(F_k\), the path can be described with modular arithmetic. The reason this works is that consecutive Fibonacci numbers are coprime, so stepping by \(F_{k-1}\) permutes the residue classes modulo \(F_k\). Step 1: Model the Banquet as a Fibonacci-Sum Graph Define $G_k=(\{1,2,\dots,F_k\},E),\qquad \{u,v\}\in E \iff u+v\in\{F_j:j\ge 1\}.$ A Hamiltonian path is an ordering \(a_1,a_2,\dots,a_{F_k}\) that uses every vertex exactly once and satisfies $a_i+a_{i+1}\in\{F_j:j\ge 1\},\qquad 1\le i \lt F_k.$ Because the graph is undirected, reversing such an ordering still gives a valid Hamiltonian path. The implementations therefore describe the path from the right end first and convert the requested left-side position only at the end....

Detailed mathematical approach

Problem Summary

Let \(F_1=F_2=1\) and \(F_{j+2}=F_{j+1}+F_j\). On the vertex set \(\{1,2,\dots,n\}\), we join \(u\) and \(v\) exactly when \(u+v\) is a Fibonacci number. The problem asks for the label at a specified place in a Hamiltonian path when \(n=F_{83}\). The crucial point is that for Fibonacci-sized graphs \(n=F_k\), the path used by the implementations is not found by search; it is given by a closed arithmetic rule.

Mathematical Approach

For graphs of size \(F_k\), the path can be described with modular arithmetic. The reason this works is that consecutive Fibonacci numbers are coprime, so stepping by \(F_{k-1}\) permutes the residue classes modulo \(F_k\).

Step 1: Model the Banquet as a Fibonacci-Sum Graph

Define

$G_k=(\{1,2,\dots,F_k\},E),\qquad \{u,v\}\in E \iff u+v\in\{F_j:j\ge 1\}.$

A Hamiltonian path is an ordering \(a_1,a_2,\dots,a_{F_k}\) that uses every vertex exactly once and satisfies

$a_i+a_{i+1}\in\{F_j:j\ge 1\},\qquad 1\le i \lt F_k.$

Because the graph is undirected, reversing such an ordering still gives a valid Hamiltonian path. The implementations therefore describe the path from the right end first and convert the requested left-side position only at the end.

Step 2: Write the Right-End Order as a Modular Walk

For \(m\ge 1\), let \(\rho_m\) be the unique integer with

$\rho_m \equiv mF_{k-1}\pmod{F_k},\qquad 1\le \rho_m \lt F_k.$

Then the right-to-left order is

$a_1=F_k,\qquad a_{2m}=\rho_m,\qquad a_{2m+1}=F_k-\rho_m,$

for every \(m\) for which the index exists. If \(F_k\) is even, the path simply ends with its final even term; for the target case \(F_{83}\) is odd, so all nonterminal terms after \(a_1\) come in even-odd pairs.

This is equivalent to the compact position formula used in the implementations. If \(r\) is the position counted from the right and \(m=\lfloor r/2\rfloor\), compute

$t \equiv mF_{k-1}\pmod{F_k},\qquad 0\le t \lt F_k,$

and interpret residue \(0\) as the vertex \(F_k\). Then

$v(r)=\begin{cases} F_k, & r=1,\\ t, & r\equiv 0 \pmod{2},\\ (F_k-t)\bmod F_k, & r\equiv 1 \pmod{2}. \end{cases}$

Step 3: Prove That Consecutive Vertices Are Adjacent

There are three kinds of neighboring pairs in the right-end description.

The opening edge is valid because

$a_1+a_2=F_k+\rho_1=F_k+F_{k-1}=F_{k+1}.$

Each even-odd pair is valid because

$a_{2m}+a_{2m+1}=\rho_m+(F_k-\rho_m)=F_k.$

Finally, between one pair and the next, we use

$\rho_{m+1}\equiv \rho_m+F_{k-1}\pmod{F_k}.$

So \(\rho_{m+1}\) is either \(\rho_m+F_{k-1}\) or \(\rho_m+F_{k-1}-F_k\), which gives

$a_{2m+1}+a_{2m+2}=(F_k-\rho_m)+\rho_{m+1}\in\{F_{k+1},F_{k-1}\}.$

All three possible sums, \(F_{k-1}\), \(F_k\), and \(F_{k+1}\), are Fibonacci numbers. Hence every consecutive pair in the constructed order is an edge of the graph.

Step 4: Prove That Every Vertex Appears Exactly Once

Since consecutive Fibonacci numbers are coprime,

$\gcd(F_{k-1},F_k)=1.$

Therefore multiplication by \(F_{k-1}\) permutes the nonzero residue classes modulo \(F_k\), so the values \(\rho_m\) are all distinct.

The complementary values \(F_k-\rho_m\) are also distinct. A collision between the two families would require

$\rho_m=F_k-\rho_j,$

which implies

$(m+j)F_{k-1}\equiv 0\pmod{F_k}.$

Because \(F_{k-1}\) is invertible modulo \(F_k\), this forces \(m+j\equiv 0\pmod{F_k}\). But in the relevant range we have \(1\le m+j \lt F_k\), so this cannot happen. Thus the construction uses each label exactly once and is a Hamiltonian path.

Step 5: Convert the Requested Position

The problem gives a position counted from the left, while the closed form is easiest from the right. If the path length is \(F_k\) and the requested left position is \(L\), then the corresponding right position is

$r=F_k-L+1.$

Since reversing the path preserves adjacency, evaluating \(v(r)\) gives the required knight directly.

Worked Example: \(n=13=F_7\)

Here \(F_{k-1}=8\). The modular residues are

$\rho_m \equiv 8m\pmod{13}\qquad(m=1,\dots,6),$

namely

$8,\ 3,\ 11,\ 6,\ 1,\ 9.$

So the right-end order is

$13,\ 8,\ 5,\ 3,\ 10,\ 11,\ 2,\ 6,\ 7,\ 1,\ 12,\ 9,\ 4.$

Reversing it gives the left-to-right order

$4,\ 9,\ 12,\ 1,\ 7,\ 6,\ 2,\ 11,\ 10,\ 3,\ 5,\ 8,\ 13.$

The consecutive sums are

$13,\ 21,\ 13,\ 8,\ 13,\ 8,\ 13,\ 21,\ 13,\ 8,\ 13,\ 21,$

all Fibonacci numbers, so the construction is visible on a small instance.

How the Code Works

The C++, Python, and Java implementations all follow the same arithmetic plan. They precompute Fibonacci numbers up to the required index, set \(n=F_{83}\), convert the requested left position \(10^{16}\) to the right-side index \(r=n-10^{16}+1\), and then evaluate the modular formula above.

For the target instance they use

$F_{82}=61305790721611591,\qquad F_{83}=99194853094755497,\qquad r=89194853094755498.$

One modular multiplication by \(F_{82}\), followed by a parity test and possibly a complement with respect to \(F_{83}\), produces the final label

$56342087360542122.$

The C++ implementation also includes small sanity checks: it finds a Hamiltonian path by brute force on a tiny graph, and for the Fibonacci-sized test case \(n=34\) it compares the entire closed form against a brute-force path. The Java implementation protects the modular product with arbitrary-precision arithmetic, Python relies on native big integers, and C++ uses a wider integer intermediate.

Complexity Analysis

If the target size is \(F_k\), generating Fibonacci numbers up to index \(k\) costs \(O(k)\) time and \(O(k)\) memory. After that one-time setup, answering the question needs only a subtraction, an integer division by \(2\), one modular multiplication, and a parity-dependent branch, so the main computation runs in \(O(1)\) time with \(O(1)\) extra working memory. The brute-force search used for validation is confined to very small checkpoints and is not part of the large-instance algorithm.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=669
  2. Hamiltonian path: Wikipedia — Hamiltonian path
  3. Fibonacci number: Wikipedia — Fibonacci number
  4. Modular arithmetic: Wikipedia — Modular arithmetic
  5. Coprime integers: Wikipedia — Coprime integers

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

Previous: Problem 668 · All Project Euler solutions · Next: Problem 670

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