Open In App

Square free semiprimes in a given range using C++ STL

Improve
Improve
Like Article
Like
Save
Share
Report
Given two integers L and R (L < = R). The task is to find all square free semiprimes in the range L to R (both inclusive). Examples:
Input : L = 1, R = 10 Output : 2 4, 6, 9, 10 are semi primes. But 6, 10 are square free semi primes. Input : L = 10, R = 20 Output : 3
Prerequisites: Sieve of Eratosthenes, upper and lower bound Understanding : Semiprimes are numbers of the form p*q where p and q are primes, not necessarily distinct. All semiprime n has only 4 factors 1, p, q, p*q where p and q are the only two prime factors and p*q = n. Naive Approach: Precompute all prime number upto $\sqrt{R}$. Find all combinations of two prime p and q such that p*q = n is between L and R. Iterating through all combinations of prime would give a time complexity of O(N $^2$). This solution, however, will not work for large L and R values. Time Complexity: O(N^2) Efficient Approach: Precompute all prime number up to $\sqrt{R}$. We can divide the problem of finding two primes p and q into a simpler form. As L $\leq$ p*q we can say that \frac{L}{p} $\leq$ q . Similarly as  p*q $\leq$ R we can say that  q $\leq$ $\frac{R}{p} . Now the problem is reduced to finding the count of q such that  \frac{L}{p} $\leq$ q $\leq$ $\frac{R}{p} for all p. Here, we can use binary search for finding upper_bound of \frac{R}{p} from list of prime numbers and subtract it from index of lower_bound of \frac{L}{p} from list of prime numbers to find the count of all q in range \frac{L}{p} to \frac{R}{p} for the given p. Repeating the above step for all prime p will give the answer for given range L to R Below is the implementation of the above approach :
// CPP program to find square free semiprimes in the range
#include <bits/stdc++.h>
using namespace std;
  
#define N 78498
  
void Sieve(int pre[])
{
    // Max size of prime array
    int MX = 1e6;
  
    // Array of prime of size 1000001.
    // will be marked true for prime, false otherwise
    // i     = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]
    // prime = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, ...}
    bool prime[MX + 1];
  
    // i -> keeps track of index of prime 
    // (current integer)
    // idx -> keeps track of index of pre
    int i = 2;
    int idx = 0;
  
    // Initialize all entries to true
    memset(prime, true, sizeof(prime));
  
    // For all i from 2 to MX iterate
    for (i = 2; i <= MX; i++)
    {
        // If i is prime
        if (prime[i]) 
        {
            // Set idx'th index of pre as i and 
            // increment idx after setting the value
            pre[idx++] = i;
  
            // For all multiple of i from 2*i to MX
            // mark them as false i.e. not prime
            for (int j = (i << 1); j <= MX; j += i)
                prime[j] = false;
        }
    }
}
  
// Function to find square free semi primes in the range
int semiPrimeCount(int L, int R)
{
  
    // Array of prime integer
    // will contain first 78498 primes
    // idx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]
    // pre = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, ...}
    int pre[N];
  
    // Prepare pre array
    Sieve(pre);
  
    // Result of current query
    int res = 0;
  
    // Offset index from start
    int j = 1;
  
    // For all prime integers p in pre 
    // from 2 to sqrt(R) iterate
    for (auto p : pre) {
        // ub_num     = count of all multiple of p less 
        //             than R => p = R/p
        //
        // ub     = iterator of first element greater 
        //         than ub_num in pre
        //
        int ub_num = R / p;
        auto ub = upper_bound(pre + j, pre + N, ub_num);
  
        // lb_num     = count of all multiple of p 
        //             less than L => p = L/p
        // If L is divisible by p increment p by 
        // 1 => p = p+1 = p+(L%p>0)
        //
        // lb     = iterator of first element greater 
        //         than or equal lb_num in pre
      
        int lb_num = (L / p) + ((L % p) > 0);
        auto lb = lower_bound(pre + j, pre + N, lb_num);
  
        // Add the difference between ub and lb
        res += ub - lb;
  
        // Increment j
        j++;
  
        // If prime p is greater than or equal to sqrt(R)
        if (p * p >= R)
            break;
    }
    return res;
}
  
// Driver code
int main()
{
    int L = 10, R = 20;
      
    // Function call
    cout << semiPrimeCount(L, R);
  
    return 0;
}

                    
Output:
3
Time Complexity: O(N*logN)

Last Updated : 21 Aug, 2019
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads