Euler Product Approximation
The Euler product for the Riemann zeta function is zeta(s) = prod_(p prime) (1 - p^(-s))^(-1). Let E(s, N) = prod_(p <= N) (1 - p^(-s))^(-1). Find floor(E(3, 10^6) x 10^15).
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Two players play a game using a deck of
- Remove the top card from the deck, taking note of its colour.
- If there is a next card and it is the same colour as the previous card they toss a fair coin. If the coin lands on heads they remove that card as well; otherwise leave it on top of the deck.
The player who removes the final card from the deck wins the game.
Some starting configurations give an advantage to one of the players; while some starting configurations are fair, in which both players have exactly
Define
Find
Problem 951: Euler Product Approximation
Mathematical Foundation
Theorem 1 (Euler Product Formula). For ,
Proof. Each factor expands as a geometric series: , convergent for . For any finite set of primes ,
by the Fundamental Theorem of Arithmetic: every positive integer factors uniquely into primes, so expanding the product yields exactly one term for each whose prime factors all lie in . As exhausts all primes, the right-hand side converges to by absolute convergence of the Dirichlet series for .
Lemma 1 (Monotonicity). for all , with as .
Proof. Each factor for . The partial product accounts for all positive integers whose prime factors are at most , a subset of all positive integers. Including additional primes strictly increases the product.
Theorem 2 (Error Bound). For and ,
Proof. We have . Taking logarithms:
By partial summation with the Prime Number Theorem :
Since for small , we obtain , and therefore .
Lemma 2 (Numerical Precision). For , the relative error is approximately . Standard IEEE 754 double-precision arithmetic (53-bit mantissa, 15.9 decimal digits) suffices for extracting .
Proof. By Theorem 2, the relative error is . Working in log-space (accumulating ), each term has relative error . Over terms, the accumulated error in is at most , which propagates to an absolute error of in . This is well within the tolerance for the 15th decimal digit.
Editorial
Compute floor(E(3, 10^6) * 10^15) where E(3, N) = prod_{p <= N} (1 - p^{-3})^{-1}. The Euler product for zeta(s) converges to Apery’s constant zeta(3) = 1.2020569… We accumulate the product in log-space for numerical stability: L = sum_{p <= N} -ln(1 - p^{-3}) E = exp(L) Key identity: zeta(s) = prod_p (1 - p^{-s})^{-1} (Re(s) > 1) Error bound: zeta(3) - E(3,N) ~ 4*zeta(3) / (N^2 * ln(N)). We sieve of Eratosthenes. We then log-space accumulation. Finally, recover product and extract answer.
Pseudocode
Sieve of Eratosthenes
Log-space accumulation
Recover product and extract answer
Complexity Analysis
- Time: for the Sieve of Eratosthenes, plus for the log-space accumulation. Total: .
- Space: for the sieve array.
For : the sieve dominates at operations; the product accumulation over primes is negligible.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
/*
* Problem 951: Euler Product Approximation
*
* Compute floor(E(3, 10^6) * 10^15) where
* E(3, N) = prod_{p <= N, p prime} (1 - p^{-3})^{-1}
*
* Algorithm:
* 1. Sieve primes up to N = 10^6
* 2. Accumulate L = sum -ln(1 - p^{-3}) in log-space (long double)
* 3. E = exp(L), answer = floor(E * 10^15)
*
* The partial Euler product converges to zeta(3) = 1.20205690315959...
* (Apery's constant) with error O(1/(N^2 ln N)).
*
* Complexity: O(N log log N) for sieve, O(pi(N)) for product.
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
const int N = 1000000;
// Sieve of Eratosthenes
vector<bool> is_prime(N + 1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; (long long)i * i <= N; i++) {
if (is_prime[i]) {
for (int j = i * i; j <= N; j += i) {
is_prime[j] = false;
}
}
}
// Accumulate Euler product in log-space using long double
long double log_prod = 0.0L;
int prime_count = 0;
for (int p = 2; p <= N; p++) {
if (is_prime[p]) {
long double term = -logl(1.0L - powl((long double)p, -3.0L));
log_prod += term;
prime_count++;
}
}
long double E = expl(log_prod);
// Verification: zeta(3) = 1.2020569031595942854...
long double zeta3 = 1.2020569031595942854L;
long double error = zeta3 - E;
cout << fixed << setprecision(18);
cout << "E(3, " << N << ") = " << (double)E << endl;
cout << "zeta(3) = " << (double)zeta3 << endl;
cout << "Error = " << (double)error << endl;
cout << "Primes used = " << prime_count << endl;
cout << endl;
// Final answer
long long answer = (long long)(E * 1e15L);
cout << answer << endl;
return 0;
}
"""
Problem 951: Euler Product Approximation
Compute floor(E(3, 10^6) * 10^15) where E(3, N) = prod_{p <= N} (1 - p^{-3})^{-1}.
The Euler product for zeta(s) converges to Apery's constant zeta(3) = 1.2020569...
We accumulate the product in log-space for numerical stability:
L = sum_{p <= N} -ln(1 - p^{-3})
E = exp(L)
Key identity: zeta(s) = prod_p (1 - p^{-s})^{-1} (Re(s) > 1)
Error bound: zeta(3) - E(3,N) ~ 4*zeta(3) / (N^2 * ln(N))
"""
from math import log, exp, isqrt
ZETA3 = 1.2020569031595942854169
def sieve_of_eratosthenes(n: int) -> list[int]:
"""Return all primes up to n using the Sieve of Eratosthenes."""
is_prime = bytearray(b'\x01') * (n + 1)
is_prime[0] = is_prime[1] = 0
for i in range(2, isqrt(n) + 1):
if is_prime[i]:
is_prime[i * i::i] = bytearray(len(is_prime[i * i::i]))
return [i for i in range(2, n + 1) if is_prime[i]]
def euler_product(s: float, N: int) -> tuple[float, list[tuple[int, float]]]:
"""Compute E(s, N) = prod_{p<=N} (1 - p^{-s})^{-1} in log-space.
Returns:
(E, checkpoints): the product value and a list of (prime, running_product)
"""
primes = sieve_of_eratosthenes(N)
log_prod = 0.0
checkpoints = []
for p in primes:
log_prod += -log(1 - p ** (-s))
if p <= 500 or p % 5000 < 10:
checkpoints.append((p, exp(log_prod)))
return exp(log_prod), checkpoints
def solve(N: int = 10**6) -> int:
"""Compute floor(E(3, 10^6) * 10^15)."""
E, _ = euler_product(3.0, N)
return int(E * 10**15)
# --- Compute answer ---
N = 10**6
E_full, checkpoints = euler_product(3.0, N)
answer = int(E_full * 10**15)
assert abs(E_full - ZETA3) < 1e-12, f"E(3,10^6) = {E_full}, expected ~{ZETA3}"
print(answer)