All Euler problems
Project Euler

Fibonacci Modular Properties

Let F_n denote the n -th Fibonacci number with F_1 = F_2 = 1. Find sum_(k=1)^(10^7) F_k mod 10^9+7.

Source sync Apr 19, 2026
Problem #0906
Level Level 32
Solved By 263
Languages C++, Python
Answer 0.0195868911
Length 319 words
modular_arithmeticlinear_algebrasequence

Problem Statement

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

Three friends attempt to collectively choose one of \(n\) options, labeled \(1,\dots ,n\), based upon their individual preferences. They choose option \(i\) if for every alternative option \(j\) at least two of the three friends prefer \(i\) over \(j\). If no such option \(i\) exists they fail to reach an agreement.

Define \(P(n)\) to be the probability the three friends successfully reach an agreement and choose one option, where each of the friends’ individual order of preference is given by a (possibly different) random permutation of \(1,\dots ,n\).

You are given \(P(3)=17/18\) and \(P(10)\approx 0.6760292265\).

Find \(P(20\,000)\). Give your answer rounded to ten places after the decimal point.

Problem 906: Fibonacci Modular Properties

Mathematical Analysis

The Fibonacci Recurrence and Its Matrix Form

The Fibonacci sequence satisfies Fn=Fn1+Fn2F_n = F_{n-1} + F_{n-2} with F1=F2=1F_1 = F_2 = 1. This recurrence can be expressed as a matrix equation:

(Fn+1Fn)=(1110)(FnFn1)(1)\begin{pmatrix} F_{n+1} \\ F_n \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix} \begin{pmatrix} F_n \\ F_{n-1} \end{pmatrix} \tag{1}

By induction:

(1110)n=(Fn+1FnFnFn1)(2)\begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}^n = \begin{pmatrix} F_{n+1} & F_n \\ F_n & F_{n-1} \end{pmatrix} \tag{2}

Proof of (2). Base case n=1n=1: the matrix is (F2F1F1F0)=(1110)\begin{pmatrix} F_2 & F_1 \\ F_1 & F_0 \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}. Inductive step: if Qn=(Fn+1FnFnFn1)Q^n = \begin{pmatrix} F_{n+1} & F_n \\ F_n & F_{n-1} \end{pmatrix}, then Qn+1=QnQ=(Fn+1+FnFn+1Fn+Fn1Fn)=(Fn+2Fn+1Fn+1Fn)Q^{n+1} = Q^n \cdot Q = \begin{pmatrix} F_{n+1}+F_n & F_{n+1} \\ F_n+F_{n-1} & F_n \end{pmatrix} = \begin{pmatrix} F_{n+2} & F_{n+1} \\ F_{n+1} & F_n \end{pmatrix}. \square

Telescoping Sum Identity

Theorem. k=1nFk=Fn+21\sum_{k=1}^{n} F_k = F_{n+2} - 1.

Proof. Write Fk=Fk+2Fk+1F_k = F_{k+2} - F_{k+1} (rearranging the recurrence). Then:

k=1nFk=k=1n(Fk+2Fk+1)=Fn+2F2=Fn+21\sum_{k=1}^{n} F_k = \sum_{k=1}^{n} (F_{k+2} - F_{k+1}) = F_{n+2} - F_2 = F_{n+2} - 1 \quad \square

Binet’s Formula and Growth Rate

The closed-form expression is:

Fn=ϕnψn5,ϕ=1+521.618,ψ=1520.618(3)F_n = \frac{\phi^n - \psi^n}{\sqrt{5}}, \quad \phi = \frac{1+\sqrt{5}}{2} \approx 1.618, \quad \psi = \frac{1-\sqrt{5}}{2} \approx -0.618 \tag{3}

Since ψ<1|\psi| < 1, Fnϕn/5F_n \sim \phi^n / \sqrt{5} for large nn. For n=107n = 10^7: log10F107107log10ϕ2,089,876\log_{10} F_{10^7} \approx 10^7 \cdot \log_{10} \phi \approx 2{,}089{,}876 digits.

Pisano Period

The Fibonacci sequence modulo mm is periodic with period π(m)\pi(m) called the Pisano period. For a prime pp:

  • If p=5p = 5: π(5)=20\pi(5) = 20
  • If p±1(mod5)p \equiv \pm 1 \pmod{5}: π(p)p1\pi(p) \mid p - 1
  • If p±2(mod5)p \equiv \pm 2 \pmod{5}: π(p)2(p+1)\pi(p) \mid 2(p + 1)

For p=109+7p = 10^9 + 7: since 109+72(mod5)10^9 + 7 \equiv 2 \pmod{5}, we have π(p)2(109+8)\pi(p) \mid 2(10^9 + 8). The exact period is very large, so we use matrix exponentiation rather than period detection.

Fast Doubling Identities

An alternative to matrix exponentiation uses the fast doubling formulas derived from (2):

F2n=Fn(2Fn+1Fn),F2n+1=Fn2+Fn+12(4)F_{2n} = F_n(2F_{n+1} - F_n), \quad F_{2n+1} = F_n^2 + F_{n+1}^2 \tag{4}

These allow computing FnmodpF_n \bmod p in O(logn)O(\log n) time without matrix multiplication overhead.

Concrete Values

nnFnF_nk=1nFk\sum_{k=1}^{n} F_kFn+21F_{n+2} - 1
1111
2122
3244
551212
1055143143
2067651771017710

Editorial

To compute QnQ^n in O(logn)O(\log n) multiplications. We compute FN+2modpF_{N+2} \bmod p where N=107N = 10^7 using matrix exponentiation or fast doubling. We then write nn in binary: n=bkbk1b0n = b_k b_{k-1} \cdots b_0. Finally, iterate over each bit from MSB to LSB: RR2R \leftarrow R^2; if bi=1b_i = 1: RRQR \leftarrow R \cdot Q.

Pseudocode

Compute $F_{N+2} \bmod p$ where $N = 10^7$ using matrix exponentiation or fast doubling
Return $(F_{N+2} - 1) \bmod p$
Write $n$ in binary: $n = b_k b_{k-1} \cdots b_0$
Initialize $R = I$ (identity)
For each bit from MSB to LSB: $R \leftarrow R^2$; if $b_i = 1$: $R \leftarrow R \cdot Q$
Each $2 \times 2$ matrix multiplication uses 8 multiplications and 4 additions modulo $p$

Proof of Correctness

Theorem. The computation S=(FN+2modp)1modpS = (F_{N+2} \bmod p) - 1 \bmod p correctly gives k=1NFkmodp\sum_{k=1}^{N} F_k \bmod p.

Proof. The telescoping identity shows S=FN+21S = F_{N+2} - 1 over Z\mathbb{Z}. Matrix exponentiation computes FN+2modpF_{N+2} \bmod p exactly (all intermediate operations are modular, and the Fibonacci recurrence is a linear recurrence preserved by modular reduction). Subtraction modulo pp is standard. \square

Complexity Analysis

  • Matrix exponentiation: O(logN)O(\log N) matrix multiplications, each O(1)O(1) for 2×22 \times 2 matrices. Total: O(logN)O(\log N) time, O(1)O(1) space.
  • Fast doubling: Same O(logN)O(\log N) complexity with smaller constant (avoids matrix overhead).
  • Iterative computation: O(N)O(N) time, O(1)O(1) space. Feasible for N=107N = 10^7 but slower.
  • Closed-form (Binet): Not directly usable modulo pp without computing 5modp\sqrt{5} \bmod p (possible since 5 is a QR mod some primes).

Answer

0.0195868911\boxed{0.0195868911}

Code

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

C++ project_euler/problem_906/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Problem 906: Fibonacci Modular Properties
 *
 * Compute sum_{k=1}^{10^7} F_k mod (10^9+7).
 *
 * Key identity: sum_{k=1}^{n} F_k = F_{n+2} - 1  (telescoping)
 *
 * Two methods for computing F(n) mod p:
 *   1. Matrix exponentiation:  Q^n gives F(n+1), F(n)  in O(log n)
 *   2. Fast doubling formulas: F(2k) = F(k)(2F(k+1)-F(k)),
 *                              F(2k+1) = F(k)^2 + F(k+1)^2
 */

const long long MOD = 1e9 + 7;

typedef vector<vector<long long>> Matrix;

/* 2x2 matrix multiplication mod p */
Matrix mat_mul(const Matrix& A, const Matrix& B) {
    Matrix C(2, vector<long long>(2, 0));
    for (int i = 0; i < 2; i++)
        for (int k = 0; k < 2; k++)
            for (int j = 0; j < 2; j++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
    return C;
}

/* Matrix binary exponentiation */
Matrix mat_pow(Matrix M, long long n) {
    Matrix R = {{1, 0}, {0, 1}};  // identity
    while (n > 0) {
        if (n & 1) R = mat_mul(R, M);
        M = mat_mul(M, M);
        n >>= 1;
    }
    return R;
}

/* Method 1: F(n) via matrix exponentiation */
long long fib_matrix(long long n) {
    if (n <= 0) return 0;
    if (n <= 2) return 1;
    Matrix Q = {{1, 1}, {1, 0}};
    Matrix R = mat_pow(Q, n - 1);
    return R[0][0];
}

/* Method 2: F(n) via fast doubling - returns (F(n), F(n+1)) */
pair<long long, long long> fib_doubling(long long n) {
    if (n == 0) return {0, 1};
    auto [a, b] = fib_doubling(n >> 1);
    long long c = a % MOD * ((2 * b - a + MOD) % MOD) % MOD;
    long long d = (a % MOD * a % MOD + b % MOD * b % MOD) % MOD;
    if (n & 1)
        return {d, (c + d) % MOD};
    else
        return {c, d};
}

long long fib_fast(long long n) {
    return fib_doubling(n).first;
}

int main() {
    long long N = 10000000;  // 10^7

    // Method 1: matrix
    long long f_mat = fib_matrix(N + 2);
    long long ans1 = (f_mat - 1 + MOD) % MOD;

    // Method 2: fast doubling
    long long f_dbl = fib_fast(N + 2);
    long long ans2 = (f_dbl - 1 + MOD) % MOD;

    assert(ans1 == ans2);

    // Verify small cases
    assert(fib_fast(1) == 1);
    assert(fib_fast(2) == 1);
    assert(fib_fast(10) == 55);
    assert(fib_fast(20) == 6765);

    // Verify telescoping for n=10
    long long sum10 = 0, a = 1, b = 1;
    for (int k = 1; k <= 10; k++) {
        sum10 += a;
        long long t = a;
        a = b;
        b = (t + b);
    }
    assert(sum10 == 143);  // F(12) - 1 = 144 - 1 = 143

    cout << ans1 << endl;
    return 0;
}