All Euler problems
Project Euler

Semidivisible Numbers

For an integer n, define lps(n) as the largest prime <= sqrt(n) and ups(n) as the smallest prime >= sqrt(n). A number n is semidivisible if exactly one of lps(n) or ups(n) divides it. Find the sum...

Source sync Apr 19, 2026
Problem #0234
Level Level 08
Solved By 3,647
Languages C++, Python
Answer 1259187438574927161
Length 280 words
number_theorymodular_arithmeticgeometry

Problem Statement

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

For an integer \(n \ge 4\), we define the lower prime square root of \(n\), denoted by \(\operatorname {lps}(n)\), as the largest prime \(\le \sqrt n\) and the upper prime square root of \(n\), \(\operatorname {ups}(n)\), as the smallest prime \(\ge \sqrt n\).

So, for example, \(\operatorname {lps}(4) = 2 = \operatorname {ups}(4)\), \(\operatorname {lps}(1000) = 31\), \(\operatorname {ups}(1000) = 37\).

Let us call an integer \(n \ge 4\) semidivisible, if one of \(\operatorname {lps}(n)\) and \(\operatorname {ups}(n)\) divides \(n\), but not both.

The sum of the semidivisible numbers not exceeding \(15\) is \(30\), the numbers are \(8\), \(10\) and \(12\).

\(15\) is not semidivisible because it is a multiple of both \(\operatorname {lps}(15) = 3\) and \(\operatorname {ups}(15) = 5\).

As a further example, the sum of the \(92\) semidivisible numbers up to \(1000\) is \(34825\).

What is the sum of all semidivisible numbers not exceeding \(999966663333\)?

Problem 234: Semidivisible Numbers

Mathematical Foundation

Theorem (Interval Decomposition). For consecutive primes p<qp < q, every integer nn with p2<n<q2p^2 < n < q^2 satisfies lps(n)=p\mathrm{lps}(n) = p and ups(n)=q\mathrm{ups}(n) = q.

Proof. Since pp and qq are consecutive primes and p2<n<q2p^2 < n < q^2, we have p<n<qp < \sqrt{n} < q. As pp is the largest prime p<n\leq p < \sqrt{n} and there is no prime between pp and qq, pp is the largest prime n\leq \sqrt{n}, so lps(n)=p\mathrm{lps}(n) = p. Similarly, qq is the smallest prime n\geq \sqrt{n}, so ups(n)=q\mathrm{ups}(n) = q. \square

Lemma (Semidivisibility Criterion). For nn in the interval (p2,q2)(p^2, q^2) with consecutive primes p<qp < q, nn is semidivisible if and only if exactly one of pnp \mid n or qnq \mid n holds.

Proof. By the theorem, lps(n)=p\mathrm{lps}(n) = p and ups(n)=q\mathrm{ups}(n) = q. By definition, nn is semidivisible when exactly one of these divides nn. \square

Lemma (Arithmetic Sum Formula). The sum of semidivisible numbers in the open interval (p2,min(q2,L))(p^2, \min(q^2, L)) equals

Σp+Σq2Σpq\Sigma_p + \Sigma_q - 2\Sigma_{pq}

where Σd\Sigma_d denotes the sum of all multiples of dd in the interval.

Proof. Let AA be the set of multiples of pp and BB the set of multiples of qq in the interval. Semidivisible numbers form the symmetric difference AB=(AB)(BA)A \triangle B = (A \setminus B) \cup (B \setminus A). Using AB=A+B2AB\sum_{A \triangle B} = \sum_A + \sum_B - 2\sum_{A \cap B} and ABA \cap B is the set of multiples of lcm(p,q)=pq\mathrm{lcm}(p,q) = pq (since p,qp, q are distinct primes), the result follows. \square

Each Σd\Sigma_d is computed as the sum of an arithmetic progression: for multiples of dd in (a,b)(a, b), the first term is d(a+1)/dd \cdot \lceil (a+1)/d \rceil, the last is d(b1)/dd \cdot \lfloor (b-1)/d \rfloor, and the sum is d(k1+k2)(k2k1+1)/2d \cdot (k_1 + k_2)(k_2 - k_1 + 1)/2.

Editorial

A number n is semidivisible if exactly one of lps(n), ups(n) divides n, where lps(n) = largest prime <= sqrt(n), ups(n) = smallest prime >= sqrt(n). We sum of multiples of d in open interval (lo, hi). Finally, sum of multiples of d in (lo, hi) exclusive.

Pseudocode

L = 999966663333
Sum of multiples of d in open interval (lo, hi)
Sum of multiples of d in (lo, hi) exclusive

Complexity Analysis

  • Time: O(LloglogL)O(\sqrt{L} \log \log \sqrt{L}) for the sieve, plus O(π(L))O(\pi(\sqrt{L})) for iterating over consecutive prime pairs. Each pair requires O(1)O(1) arithmetic. Total: O(LloglogL)O(\sqrt{L} \log \log \sqrt{L}).
  • Space: O(L)O(\sqrt{L}) for the sieve.

Answer

1259187438574927161\boxed{1259187438574927161}

Code

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

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

typedef long long ll;
typedef __int128 lll;

// Sum of multiples of d in open interval (lo, hi), i.e., lo < n < hi and d | n
// Returns sum as __int128 to avoid overflow
lll sum_multiples(ll d, ll lo, ll hi) {
    // First multiple of d greater than lo
    ll first_k = lo / d + 1;
    // Last multiple of d less than hi
    ll last_k = (hi - 1) / d;
    if (first_k > last_k) return 0;
    // Sum = d * (first_k + first_k+1 + ... + last_k) = d * (last_k - first_k + 1) * (first_k + last_k) / 2
    lll cnt = last_k - first_k + 1;
    lll s = cnt * (first_k + last_k) / 2;
    return (lll)d * s;
}

int main() {
    const ll LIMIT = 999966663333LL;
    const int SIEVE_SIZE = 1100000; // primes up to ~1.1M covers sqrt(LIMIT) ~ 999983

    // Sieve
    vector<bool> is_prime(SIEVE_SIZE + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; (ll)i * i <= SIEVE_SIZE; i++)
        if (is_prime[i])
            for (int j = i * i; j <= SIEVE_SIZE; j += i)
                is_prime[j] = false;

    vector<ll> primes;
    for (int i = 2; i <= SIEVE_SIZE; i++)
        if (is_prime[i])
            primes.push_back(i);

    lll total = 0;

    for (int i = 0; i + 1 < (int)primes.size(); i++) {
        ll p = primes[i];
        ll q = primes[i + 1];
        ll lo = p * p;    // exclusive lower bound
        ll hi = q * q;    // exclusive upper bound (or LIMIT+1)

        if (lo >= LIMIT) break;
        if (hi > LIMIT + 1) hi = LIMIT + 1;

        // Sum of semidivisible in (lo, hi):
        // divisible by exactly one of p, q
        // = S_p + S_q - 2*S_{pq}
        lll sp = sum_multiples(p, lo, hi);
        lll sq = sum_multiples(q, lo, hi);
        lll spq = sum_multiples(p * q, lo, hi);
        total += sp + sq - 2 * spq;
    }

    // Print __int128
    // Convert to string
    ll hi_part = (ll)(total / 1000000000000000000LL);
    ll lo_part = (ll)(total % 1000000000000000000LL);
    if (hi_part > 0)
        printf("%lld%018lld\n", hi_part, lo_part);
    else
        printf("%lld\n", lo_part);

    return 0;
}