cppAcademy
FROM LEARNING TO COMPETING

Intermediate.
Put your skills to the test.

Bulgarian Informatics Group D · 2007–2026

270 independently explained problems: 54 Municipal, 54 Regional, 105 National Olympiad and 57 Autumn Tournament tasks. Start with the easier tasks and work upwards. Difficulty labels are learning estimates, not official ratings; Group D also includes challenging national-level problems. The six 2017 National tasks shared by Groups C and D use their existing permanent URLs. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP D2024 · MediumPrime sieve and prefix sums

Range Counts with Three Distinct Prime Factors

National Olympiad — National round (2024 season)

Submission name: prime3.cpp

Problem summary

Count integers in each interval [a,b] with exactly three distinct prime divisors, regardless of their multiplicities.

Input

t followed by t pairs a b.

Output

One count per query.

Constraints

0<t<1000; 0<a<b<1000000.

Worked example

Input and output for the worked example discussed below.

Input

3
1 100
140 180
1000 1010

Output

8
9
5

Solution analysis

  1. Use a sieve counting distinct prime factors. A zero count at p≥2 identifies a prime; increment all its multiples once for this prime.
  2. Build prefix[x]=prefix[x−1]+[count[x]==3]. Each query answer is prefix[b]−prefix[a−1], so intervals need no repeated factorization.
  3. In [1,100], the qualifying numbers are 30,42,60,66,70,78,84,90. For example 60=2²×3×5 has three distinct primes, while 16=2⁴ has only one.

Why it works

Every composite has already been visited by a smaller prime, so the sieve identifies all primes correctly. Each prime contributes once to its multiples, giving exact distinct-factor counts. Prefix subtraction then isolates each closed interval.

Complexity: O(U log log U+t) time and O(U) space for U=999999, with O(1) per query.

Watch out. Count distinct primes rather than factors with multiplicity. One has zero primes. Use a−1 for the left endpoint.

Commented C++17 solution

An independently written complete program with standard headers.

#include<iostream>
#include<vector>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    const int limit=999999;
    vector<unsigned char>count(limit+1,0);
    for(int prime=2;prime<=limit;prime++){
        if(count[prime]==0){
            for(int multiple=prime;multiple<=limit;multiple+=prime){
                count[multiple]++;
            }
        }
    }
    vector<int>prefix(limit+1,0);
    for(int value=1;value<=limit;value++){
        // Prefix subtraction answers each inclusive interval.
        prefix[value]=prefix[value-1]+(count[value]==3);
    }
    int queries;
    cin>>queries;
    while(queries-->0){
        int a;
        int b;
        cin>>a>>b;
        cout<<prefix[b]-prefix[a-1]<<'\n';
    }
}

Source: Arena Olimpiici ↗