All Euler problems
Project Euler

Prime Counting Function

Let pi(x) denote the number of primes not exceeding x. Compute sum_(k=1)^(10^4) pi(k^2).

Source sync Apr 19, 2026
Problem #0954
Level Level 36
Solved By 192
Languages C++, Python
Answer 736463823
Length 365 words
number_theoryanalytic_mathlinear_algebra

Problem Statement

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

A positive integer is called extitheptaphobic if it is not divisible by seven and no number divisible by seven can be produced by swapping two of its digits. Note that leading zeros are not allowed before or after the swap.

For example, \(17\) and \(1305\) are heptaphobic, but \(14\) and \(132\) are not because \(14\) and \(231\) are divisible by seven.

Let \(C(N)\) count heptaphobic numbers smaller than \(N\). You are given \(C(100) = 74\) and \(C(10^4) = 3737\).

Find \(C(10^{13})\).

Problem 954: Prime Counting Function

Mathematical Analysis

The Prime Counting Function

The prime counting function π(x)\pi(x) gives the number of primes pxp \le x. By the Prime Number Theorem (proved independently by Hadamard and de la Vallee Poussin in 1896):

π(x)xlnxas x\pi(x) \sim \frac{x}{\ln x} \quad \text{as } x \to \infty

A better approximation is the logarithmic integral: π(x)Li(x)=2xdtlnt\pi(x) \approx \operatorname{Li}(x) = \int_2^x \frac{dt}{\ln t}.

Estimating the Sum

We need π(k2)\pi(k^2) for k=1,,104k = 1, \ldots, 10^4, so the largest argument is (104)2=108(10^4)^2 = 10^8. By PNT:

π(k2)k2ln(k2)=k22lnk\pi(k^2) \approx \frac{k^2}{\ln(k^2)} = \frac{k^2}{2\ln k}

The sum is approximately:

k=1Nk22lnk2Nx22lnxdxN36lnN\sum_{k=1}^{N} \frac{k^2}{2\ln k} \approx \int_2^{N} \frac{x^2}{2\ln x}\,dx \approx \frac{N^3}{6\ln N}

For N=104N = 10^4: 101264ln101.8×1010\frac{10^{12}}{6 \cdot 4 \ln 10} \approx 1.8 \times 10^{10}, which is in the right ballpark.

Prefix Sum Approach

Theorem (Prefix Sum Method). If P[n]=j=2n1[j is prime]P[n] = \sum_{j=2}^{n} \mathbf{1}[\text{j is prime}] is the prefix sum of the prime indicator, then π(n)=P[n]\pi(n) = P[n] for all n2n \ge 2, and the desired sum is k=1NP[k2]\sum_{k=1}^{N} P[k^2].

This allows us to compute all required values with a single sieve followed by O(N)O(N) lookups.

Concrete Examples

kkk2k^2π(k2)\pi(k^2)
110
242
394
4166
5259
1010025
100100001229
100010610^678498

Partial sums: k=110π(k2)=0+2+4+6+9+8+15+18+21+25=108\sum_{k=1}^{10} \pi(k^2) = 0 + 2 + 4 + 6 + 9 + 8 + 15 + 18 + 21 + 25 = 108. Wait, let me be precise: π(36)=11,π(49)=15,π(64)=18,π(81)=22\pi(36)=11, \pi(49)=15, \pi(64)=18, \pi(81)=22.

Derivation

Editorial

Compute sum_{k=1}^{10^4} pi(k^2) where pi(x) is the prime counting function. Algorithm: 1. Sieve of Eratosthenes up to (10^4)^2 = 10^8 2. Build prefix sum of prime indicator 3. Sum pi(k^2) for k = 1, …, 10^4 Complexity: O(M log log M) time, O(M) space, M = 10^8. We sieve of Eratosthenes** up to M=(104)2=108M = (10^4)^2 = 10^8. Finally, build prefix sum** array: P[n]=P[n1]+[n is prime]P[n] = P[n-1] + [n \text{ is prime}] for n=2,,Mn = 2, \ldots, M.

Pseudocode

Sieve of Eratosthenes** up to $M = (10^4)^2 = 10^8$
Build prefix sum** array: $P[n] = P[n-1] + [n \text{ is prime}]$ for $n = 2, \ldots, M$
Accumulate** $S = \sum_{k=1}^{10^4} P[k^2]$

Memory Optimization

A boolean sieve for 10810^8 entries requires 100 MB. Using a bitset reduces this to ~12.5 MB. Alternatively, a segmented sieve can be used with O(M)O(\sqrt{M}) memory, though the prefix-sum approach requires storing cumulative counts.

Verification

Cross-check with known values: π(108)=5761455\pi(10^8) = 5761455 (well-established). The sum of the first few terms can be verified manually.

Proof of Correctness

Theorem. The Sieve of Eratosthenes correctly identifies all primes up to MM.

Proof. If nMn \le M is composite, then n=abn = ab with 1<ab1 < a \le b, so aMa \le \sqrt{M}. The sieve marks nn as composite when processing the smallest prime factor of nn, which is aM\le a \le \sqrt{M}. Hence every composite number is correctly identified. \square

Corollary. The prefix sum P[n]P[n] equals π(n)\pi(n) for all 1nM1 \le n \le M.

Complexity Analysis

  • Sieve: O(MloglogM)O(M \log \log M) time, O(M)O(M) space (or O(M/8)O(M / 8) with bitset).
  • Prefix sum: O(M)O(M) time.
  • Final summation: O(M)O(\sqrt{M}) time.
  • Total: O(MloglogM)O(M \log \log M) with M=108M = 10^8.

Answer

736463823\boxed{736463823}

Code

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

C++ project_euler/problem_954/solution.cpp
/*
 * Problem 954: Prime Counting Function
 *
 * Compute sum_{k=1}^{10^4} pi(k^2).
 *
 * Algorithm:
 *   1. Sieve primes up to (10^4)^2 = 10^8
 *   2. Build prefix sum array of prime indicator
 *   3. Sum pi(k^2) for k = 1 to 10^4
 *
 * Complexity: O(M log log M), M = 10^8.
 * Memory: ~100 MB for boolean sieve + prefix sums.
 */

#include <bits/stdc++.h>
using namespace std;

int main() {
    const int N = 10000;
    const int M = N * N;  // 10^8

    // Sieve of Eratosthenes
    vector<bool> is_prime(M + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; (long long)i * i <= M; i++) {
        if (is_prime[i]) {
            for (int j = i * i; j <= M; j += i) {
                is_prime[j] = false;
            }
        }
    }

    // Build prefix sum: pi[n] = number of primes <= n
    vector<int> pi(M + 1, 0);
    for (int n = 1; n <= M; n++) {
        pi[n] = pi[n - 1] + (is_prime[n] ? 1 : 0);
    }

    // Sum pi(k^2) for k = 1 to N
    long long total = 0;
    for (int k = 1; k <= N; k++) {
        total += pi[(long long)k * k];
    }

    cout << total << endl;
    return 0;
}