All Euler problems
Project Euler

Chip Defects

k = 20,000 defects are randomly distributed amongst n = 1,000,000 integrated-circuit chips (each defect independently and uniformly at random). Let p(k,n) represent the probability that there is a...

Source sync Apr 19, 2026
Problem #0307
Level Level 11
Solved By 1,936
Languages C++, Python
Answer 0.7311720251
Length 245 words
probabilitybrute_forcelinear_algebra

Problem Statement

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

defects are randomly distributed amongst integrated-circuit chips produced by a factory (any number of defects may be found on a chip and each defect is independent of the other defects).

Let represent the probability that there is a chip with at least defects.
For instance .

Find and give your answer rounded to decimal places in the form 0.abcdefghij.

Problem 307: Chip Defects

Mathematical Analysis

Complementary Probability

We compute P(complement) = probability that NO chip has 3+ defects (every chip has 0, 1, or 2 defects), then p = 1 - P(complement).

Exact Formula

If exactly j chips have 2 defects, then k - 2j chips have exactly 1 defect:

P(complement)=j=0k/2(nj)(njk2j)k!2jnkP(\text{complement}) = \sum_{j=0}^{\lfloor k/2 \rfloor} \binom{n}{j}\binom{n-j}{k-2j}\frac{k!}{2^j \cdot n^k}

Efficient Computation via Ratio Method

Let TjT_j be the j-th term. The first term is:

T0=i=0k1ninT_0 = \prod_{i=0}^{k-1}\frac{n-i}{n}

The ratio of consecutive terms:

Tj+1Tj=(k2j)(k2j1)2(j+1)(nk+j+1)\frac{T_{j+1}}{T_j} = \frac{(k-2j)(k-2j-1)}{2(j+1)(n-k+j+1)}

Numerical Stability

Since T_0 ~ 10^{-88}, we compute in log-space using the log-sum-exp technique:

  1. Compute log(T_j) for each j by accumulating log-ratios
  2. Find the maximum log-term
  3. Sum exp(log(T_j) - max) to avoid underflow
  4. Recover P(complement) and compute p = 1 - P(complement)

Derivation of the Ratio

Tj+1Tj=(nj+1)(nj1k2j2)(nj)(njk2j)12=(k2j)(k2j1)2(j+1)(nk+j+1)\frac{T_{j+1}}{T_j} = \frac{\binom{n}{j+1}\binom{n-j-1}{k-2j-2}}{\binom{n}{j}\binom{n-j}{k-2j}} \cdot \frac{1}{2} = \frac{(k-2j)(k-2j-1)}{2(j+1)(n-k+j+1)}

Correctness

Theorem. The method described above computes exactly the quantity requested in the problem statement.

Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer. \square

Complexity

  • Time: O(k)
  • Space: O(k) for log-terms (or O(1) with streaming)

Answer

0.7311720251\boxed{0.7311720251}

Code

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

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

int main() {
    // Chip Defects: p(k,n) = probability that at least one chip has 3+ defects
    // k=20000 defects, n=1000000 chips
    // P(no chip has 3+) = sum_{j=0}^{k/2} C(n,j)*C(n-j,k-2j)*k!/(2^j * n^k)
    // p(k,n) = 1 - P(no chip has 3+)
    //
    // Use ratio method in log space:
    // T_{j+1}/T_j = (k-2j)(k-2j-1) / (2(j+1)(n-k+j+1))

    long long n = 1000000;
    long long k = 20000;

    // Compute log(T_0) = sum_{i=0}^{k-1} log((n-i)/n)
    long double log_T0 = 0.0L;
    for (long long i = 0; i < k; i++) {
        log_T0 += logl((long double)(n - i) / (long double)n);
    }

    // log_T0 is very negative. We sum T_j using log-sum-exp.
    // log(T_j) = log(T_0) + sum of log(ratios)
    // We collect all log(T_j) and use log-sum-exp

    // Actually, let's find the maximum term first, then sum relative to it
    // Compute all log(T_j) values
    vector<long double> log_terms;
    long double log_Tj = log_T0;
    log_terms.push_back(log_Tj);

    for (long long j = 0; j < k / 2; j++) {
        long double log_ratio = logl((long double)(k - 2*j)) + logl((long double)(k - 2*j - 1))
                              - logl(2.0L) - logl((long double)(j + 1)) - logl((long double)(n - k + j + 1));
        log_Tj += log_ratio;
        log_terms.push_back(log_Tj);
        if (log_Tj < log_T0 - 100.0L) break; // negligible
    }

    // Log-sum-exp
    long double max_log = *max_element(log_terms.begin(), log_terms.end());
    long double sum_exp = 0.0L;
    for (auto lt : log_terms) {
        sum_exp += expl(lt - max_log);
    }
    long double log_P_complement = max_log + logl(sum_exp);

    // P(no chip has 3+) = exp(log_P_complement)
    // p(k,n) = 1 - exp(log_P_complement)
    // But if P_complement is close to 1, we need careful subtraction
    // log_P_complement should be close to log(0.27) ~ -1.3

    long double P_complement = expl(log_P_complement);
    long double answer = 1.0L - P_complement;

    printf("%.10Lf\n", answer);
    return 0;
}