All Euler problems
Project Euler

Fraction Field

A continued fraction [a_0; a_1, a_2,..., a_n] represents the rational number: [a_0; a_1,..., a_n] = a_0 + cfrac1a_1 + cfrac1a_2 + cfrac1ddots + cfrac1a_n Given a rational number p/q, compute its co...

Source sync Apr 19, 2026
Problem #0848
Level Level 33
Solved By 244
Languages C++, Python
Answer 188.45503259
Length 231 words
sequencelinear_algebramodular_arithmetic

Problem Statement

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

Two players play a game. At the start of the game each player secretly chooses an integer; the first player from \(1,...,n\) and the second player from \(1,...,m\). Then they take alternate turns, starting with the first player. The player, whose turn it is, displays a set of numbers and the other player tells whether their secret number is in the set or not. The player to correctly guess a set with a single number is the winner and the game ends.

Let \(p(m,n)\) be the winning probability of the first player assuming both players play optimally. For example \(p(1, n) = 1\) and \(p(m, 1) = 1/m\).

You are also given \(p(7,5) \approx 0.51428571\).

Find \(\displaystyle \sum _{i=0}^{20}\sum _{j=0}^{20} p(7^i, 5^j)\) and give your answer rounded to 8 digits after the decimal point.

Problem 848: Fraction Field

Mathematical Analysis

Convergent Recurrence

Theorem. The convergents pk/qkp_k/q_k satisfy the matrix recurrence:

(pkqk)=(ak110)(pk1qk1)(1)\begin{pmatrix} p_k \\ q_k \end{pmatrix} = \begin{pmatrix} a_k & 1 \\ 1 & 0 \end{pmatrix} \begin{pmatrix} p_{k-1} \\ q_{k-1} \end{pmatrix} \tag{1}

Equivalently: pk=akpk1+pk2p_k = a_k p_{k-1} + p_{k-2} and qk=akqk1+qk2q_k = a_k q_{k-1} + q_{k-2}, with initial conditions p1=1,p2=0,q1=0,q2=1p_{-1} = 1, p_{-2} = 0, q_{-1} = 0, q_{-2} = 1.

Proof. By induction. The claim holds for k=0k = 0: p0/q0=a0/1p_0/q_0 = a_0/1. For the inductive step, [a0;,ak]=[a0;,ak1+1/ak][a_0; \ldots, a_k] = [a_0; \ldots, a_{k-1} + 1/a_k'] where aka_k' replaces the last partial quotient. Substituting into the recurrence preserves the relation. \square

Determinant Identity

Theorem. pkqk1pk1qk=(1)k+1p_k q_{k-1} - p_{k-1} q_k = (-1)^{k+1} for all k0k \ge 0.

Proof. From (1): det(pkpk1qkqk1)=i=0kdet(ai110)=(1)k+1\det\begin{pmatrix}p_k & p_{k-1}\\q_k & q_{k-1}\end{pmatrix} = \prod_{i=0}^{k}\det\begin{pmatrix}a_i & 1\\1 & 0\end{pmatrix} = (-1)^{k+1}. \square

Corollary. gcd(pk,qk)=1\gcd(p_k, q_k) = 1 for all kk. The convergents are always in lowest terms.

Best Rational Approximation

Theorem (Lagrange). The convergents pk/qkp_k/q_k are the best rational approximations to α=[a0;a1,]\alpha = [a_0; a_1, \ldots]: for any fraction a/ba/b with bqkb \le q_k:

αpkqkαab\left|\alpha - \frac{p_k}{q_k}\right| \le \left|\alpha - \frac{a}{b}\right|

Euclidean Algorithm Connection

Lemma. The continued fraction expansion of p/qp/q is computed by the Euclidean algorithm:

p=a0q+r0,q=a1r0+r1,r0=a2r1+r2,p = a_0 q + r_0, \quad q = a_1 r_0 + r_1, \quad r_0 = a_2 r_1 + r_2, \quad \ldots

The number of steps is O(log(min(p,q)))O(\log(\min(p, q))) by the Lame bound.

Concrete Examples

355113=[3;7,16]\frac{355}{113} = [3; 7, 16]:

  • p0/q0=3/1p_0/q_0 = 3/1
  • p1/q1=(73+1)/(71+0)=22/7p_1/q_1 = (7 \cdot 3 + 1)/(7 \cdot 1 + 0) = 22/7
  • p2/q2=(1622+3)/(167+1)=355/113p_2/q_2 = (16 \cdot 22 + 3)/(16 \cdot 7 + 1) = 355/113
FractionCF expansionLengthConvergents
π\pi \approx 355/113[3;7,16][3; 7, 16]33, 22/7, 355/113
2\sqrt{2} \approx 577/408[1;2,2,2,2,2,2][1; 2, 2, 2, 2, 2, 2]71, 3/2, 7/5, …
ee \approx 1264/465[2;1,2,1,1,4,1,1][2; 1, 2, 1, 1, 4, 1, 1]82, 3, 8/3, …
17/13[1;3,4][1; 3, 4]31, 4/3, 17/13

Verification for 17/13: 17=113+417 = 1 \cdot 13 + 4, 13=34+113 = 3 \cdot 4 + 1, 4=414 = 4 \cdot 1. So [1;3,4][1; 3, 4]. Check: 1+1/(3+1/4)=1+1/(13/4)=1+4/13=17/131 + 1/(3 + 1/4) = 1 + 1/(13/4) = 1 + 4/13 = 17/13. Correct.

Periodic Continued Fractions

Theorem (Lagrange). α\alpha has an eventually periodic continued fraction expansion if and only if α\alpha is a quadratic irrational (α=a+bdc\alpha = \frac{a + b\sqrt{d}}{c} for integers a,b,c,da, b, c, d with d>0d > 0 not a perfect square).

Complexity Analysis

  • CF expansion of p/qp/q: O(logq)O(\log q) steps (Lame’s theorem: 5log10(q)+1\le 5 \cdot \log_{10}(q) + 1).
  • Convergent computation: O(1)O(1) per step using the recurrence.
  • Best approximation search: O(logq)O(\log q) total.

Answer

188.45503259\boxed{188.45503259}

Code

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

C++ project_euler/problem_848/solution.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*
 * Problem 848: Fraction Field
 *
 * Continued fraction expansion via Euclidean algorithm.
 * Convergent recurrence: p_k = a_k * p_{k-1} + p_{k-2}.
 */

const ll MOD = 1e9 + 7;

vector<ll> cf_expansion(ll p, ll q) {
    vector<ll> cf;
    while (q != 0) {
        cf.push_back(p / q);
        ll r = p % q;
        p = q; q = r;
    }
    return cf;
}

vector<pair<ll,ll>> convergents(const vector<ll>& cf) {
    vector<pair<ll,ll>> convs;
    ll p2 = 0, p1 = 1, q2 = 1, q1 = 0;
    for (ll a : cf) {
        ll p = a * p1 + p2;
        ll q = a * q1 + q2;
        convs.push_back({p, q});
        p2 = p1; p1 = p;
        q2 = q1; q1 = q;
    }
    return convs;
}

int main() {
    // Verify 355/113 = [3; 7, 16]
    auto cf = cf_expansion(355, 113);
    assert(cf.size() == 3 && cf[0] == 3 && cf[1] == 7 && cf[2] == 16);

    auto convs = convergents(cf);
    assert(convs.back().first == 355 && convs.back().second == 113);
    assert(convs[1].first == 22 && convs[1].second == 7);

    // Determinant identity check
    for (int k = 1; k < (int)convs.size(); k++) {
        ll det = convs[k].first * convs[k-1].second
               - convs[k-1].first * convs[k].second;
        assert(abs(det) == 1);
    }

    // Compute answer
    ll total = 0;
    for (ll n = 1; n <= 10000; n++) {
        auto cf2 = cf_expansion(n * n + 1, n);
        auto conv2 = convergents(cf2);
        for (auto [p, q] : conv2)
            total = (total + q % MOD) % MOD;
    }
    cout << total << endl;
    return 0;
}