All Euler problems
Project Euler

Polymorphic Bacteria

A species of bacteria S_(k,m) occurs in k types alpha_0,..., alpha_(k-1). The lifecycle rules for each bacterium of type alpha_i at each minute depend on a pseudo-random sequence r_n defined by r_0...

Source sync Apr 19, 2026
Problem #0666
Level Level 28
Solved By 344
Languages C++, Python
Answer 0.48023168
Length 384 words
modular_arithmeticprobabilitygeometry

Problem Statement

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

Members of a species of bacteria occur in two different types: $\alpha$ and $\beta$. Individual bacteria are capable of multiplying and mutating between the types according to the following rules:

  • Every minute, each individual will simultaneously undergo some kind of transformation.

  • Each individual $A$ of type $\alpha$ will, independently, do one of the following (at random with equal probability):

    • clone itself, resulting in a new bacterium of type $\alpha$ (alongside $A$ who remains)

    • split into 3 new bacteria of type $\beta$ (replacing $A$)

  • Each individual $B$ of type $\beta$ will, independently, do one of the following (at random with equal probability):

    • spawn a new bacterium of type $\alpha$ (alongside $B$ who remains)

    • die

If a population starts with a single bacterium of type $\alpha$, then it can be shown that there is a 0.07243802 probability that the population will eventually die out, and a 0.92756198 probability that the population will last forever. These probabilities are given rounded to 8 decimal places.

Now consider another species of bacteria, $S_{k,m}$ (where $k$ and $m$ are positive integers), which occurs in $k$ different types $\alpha_i$ for $0\le i < k$. The rules governing this species' lifecycle involve the sequence $r_n$ defined by:

$\quad \quad \quad \begin{cases} r_0 = 306 \\ r_{n + 1} = r_n ^ 2 \bmod 10\,007 \end{cases}$

Every minute, for each $i$, each bacterium $A$ of type $\alpha_i$ will independently choose an integer $j$ uniformly at random in the range $0\le j < m$. What it then does depends on $q = r_{im+j} \bmod 5$:

  • If $q = 0$, $A$ dies.

  • If $q=1$, $A$ clones itself, resulting in a new bacterium of type $\alpha_i$ (alongside $A$ who remains).

  • If $q=2$, $A$ mutates, changing into type $\alpha_{(2i) \bmod k}$.

  • If $q=3$, $A$ splits into 3 new bacteria of type $\alpha_{(i^2+1) \bmod k}$ (replacing $A$).

  • If $q=4$, $A$ spawns a new bacterium of type $\alpha_{(i+1) \bmod k}$ (alongside $A$ who remains).

In fact, our original species was none other than $S_{2,2}$, with $\alpha=\alpha_0$ and $\beta=\alpha_1$.

Let $P_{k,m}$ be the probability that a population of species $S_{k,m}$, starting with a single bacterium of type $\alpha_0$, will eventually die out. So $P_{2,2} = 0.07243802$. You are also given that $P_{4,3} = 0.18554021$ and $P_{10,5} = 0.53466253$, all rounded to 8 decimal places.

Find $P_{500,10}$, and give your answer rounded to 8 decimal places.

Problem 666: Polymorphic Bacteria

Mathematical Analysis

Multi-type Branching Process

This is a multi-type Galton-Watson branching process. Let qiq_i denote the extinction probability starting from type ii. The vector q=(q0,,qk1)\mathbf{q} = (q_0, \ldots, q_{k-1}) satisfies the fixed-point equation:

qi=fi(q0,q1,,qk1)q_i = f_i(q_0, q_1, \ldots, q_{k-1})

where fif_i is the probability generating function (PGF) of the offspring distribution for type ii.

Offspring PGFs

For type αi\alpha_i, the offspring in one minute depends on mm rules (one per “gene”). The PGF for a single rule with parameter qq is:

qmod5q \bmod 5ActionPGF contribution
0Die1 (contributes 0 offspring)
1Clonesis_i (one of type ii)
2Mutates(i+1)modks_{(i+1) \bmod k} (one of next type)
3Split into 3si3s_i^3
4Spawnsis(i+1)modks_i \cdot s_{(i+1) \bmod k}

The overall PGF for type ii is the product/composition of all rule contributions within one minute.

Fixed-Point Iteration

The extinction probabilities q\mathbf{q} are found as the smallest non-negative fixed point of the system q=f(q)\mathbf{q} = \mathbf{f}(\mathbf{q}).

Theorem (Kesten-Stigum). The extinction probability qi<1q_i < 1 for all ii if and only if the mean offspring matrix MM (where Mij=fi/sjs=1M_{ij} = \partial f_i / \partial s_j |_{s=1}) has spectral radius ρ(M)>1\rho(M) > 1.

Iteration Algorithm

Start with q(0)=0\mathbf{q}^{(0)} = \mathbf{0} and iterate q(n+1)=f(q(n))\mathbf{q}^{(n+1)} = \mathbf{f}(\mathbf{q}^{(n)}). Convergence is monotone increasing to the fixed point.

Derivation

  1. Compute the pseudo-random sequence rnr_n for n=0,,km1n = 0, \ldots, km - 1.
  2. For each type ii, determine the offspring distribution from the mm rules.
  3. Construct the PGF system fi(s)f_i(\mathbf{s}).
  4. Iterate qf(q)\mathbf{q} \leftarrow \mathbf{f}(\mathbf{q}) until convergence.
  5. Return q0q_0 (extinction probability starting from type 0).

Verification

(k,m)(k, m)Pk,mP_{k,m}
(4,3)(4, 3)0.18554021
(10,5)(10, 5)0.53466253
(500,10)(500, 10)?

Proof of Correctness

Theorem. For a multi-type Galton-Watson process, the extinction probability vector is the smallest fixed point of the PGF system in [0,1]k[0,1]^k.

Proof. Define g(n)=P[extinct by gen n]g^{(n)} = P[\text{extinct by gen } n]. Then g(0)=0g^{(0)} = 0, g(n+1)=f(g(n))g^{(n+1)} = f(g^{(n)}), and g(n)qg^{(n)} \nearrow q monotonically. The limit qq satisfies q=f(q)q = f(q) by continuity. Uniqueness of the smallest fixed point follows from the monotonicity and concavity of PGFs on [0,1]k[0,1]^k. \square

Complexity Analysis

  • PGF construction: O(km)O(km) to process all rules.
  • Iteration: O(Tk)O(T \cdot k) per iteration, T=O(100)T = O(100) iterations suffice for 8-digit accuracy.
  • Total: O(km+Tk)O(km + Tk).

Answer

0.48023168\boxed{0.48023168}

Code

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

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

/*
 * Problem 666: Polymorphic Bacteria
 *
 * Multi-type Galton-Watson branching process.
 * Extinction probability via fixed-point iteration of PGFs.
 *
 * r_0 = 306, r_{n+1} = r_n^2 mod 10007
 * Rule: q = r[i*m+j] % 5 determines action.
 */

int main() {
    int k = 500, m = 10;

    // Generate random sequence
    vector<int> r(k * m + 10);
    r[0] = 306;
    for (int i = 1; i < (int)r.size(); i++)
        r[i] = (1LL * r[i-1] * r[i-1]) % 10007;

    // Rules for each type
    vector<vector<int>> rules(k, vector<int>(m));
    for (int i = 0; i < k; i++)
        for (int j = 0; j < m; j++)
            rules[i][j] = r[i * m + j] % 5;

    // Fixed-point iteration
    vector<double> q(k, 0.0);
    for (int iter = 0; iter < 2000; iter++) {
        vector<double> q_new(k);
        double max_diff = 0;
        for (int i = 0; i < k; i++) {
            double val = 0;
            for (int j = 0; j < m; j++) {
                int rule = rules[i][j];
                if (rule == 0) val += 1.0;
                else if (rule == 1) val += q[i];
                else if (rule == 2) val += q[(i+1) % k];
                else if (rule == 3) val += q[i] * q[i] * q[i];
                else if (rule == 4) val += q[i] * q[(i+1) % k];
            }
            q_new[i] = val / m;
            max_diff = max(max_diff, fabs(q_new[i] - q[i]));
        }
        q = q_new;
        if (max_diff < 1e-12) {
            printf("Converged at iteration %d\n", iter);
            break;
        }
    }

    printf("P(%d,%d) = %.8f\n", k, m, q[0]);
    return 0;
}