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...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
For an integer \(n \ge 4\), we define the
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\)
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 , every integer with satisfies and .
Proof. Since and are consecutive primes and , we have . As is the largest prime and there is no prime between and , is the largest prime , so . Similarly, is the smallest prime , so .
Lemma (Semidivisibility Criterion). For in the interval with consecutive primes , is semidivisible if and only if exactly one of or holds.
Proof. By the theorem, and . By definition, is semidivisible when exactly one of these divides .
Lemma (Arithmetic Sum Formula). The sum of semidivisible numbers in the open interval equals
where denotes the sum of all multiples of in the interval.
Proof. Let be the set of multiples of and the set of multiples of in the interval. Semidivisible numbers form the symmetric difference . Using and is the set of multiples of (since are distinct primes), the result follows.
Each is computed as the sum of an arithmetic progression: for multiples of in , the first term is , the last is , and the sum is .
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: for the sieve, plus for iterating over consecutive prime pairs. Each pair requires arithmetic. Total: .
- Space: for the sieve.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#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;
}
"""
Problem 234: Semidivisible Numbers
Find the sum of all semidivisible numbers not exceeding 999966663333.
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).
"""
def sieve_primes(n):
is_p = bytearray(b'\x01') * (n + 1)
is_p[0] = is_p[1] = 0
for i in range(2, int(n**0.5) + 1):
if is_p[i]:
is_p[i*i::i] = bytearray(len(is_p[i*i::i]))
return [i for i in range(2, n + 1) if is_p[i]]
def sum_multiples(d, lo, hi):
"""Sum of multiples of d in open interval (lo, hi)."""
first_k = lo // d + 1
last_k = (hi - 1) // d
if first_k > last_k:
return 0
cnt = last_k - first_k + 1
return d * cnt * (first_k + last_k) // 2
def solve():
LIMIT = 999966663333
primes = sieve_primes(1100000)
total = 0
for i in range(len(primes) - 1):
p = primes[i]
q = primes[i + 1]
lo = p * p
hi = q * q
if lo >= LIMIT:
break
if hi > LIMIT + 1:
hi = LIMIT + 1
sp = sum_multiples(p, lo, hi)
sq = sum_multiples(q, lo, hi)
spq = sum_multiples(p * q, lo, hi)
total += sp + sq - 2 * spq
print(total)
if __name__ == "__main__":
solve()