Skip to content
Related Articles

Related Articles

Count of numbers up to N having only 4 factors or divisors

View Discussion
Improve Article
Save Article
  • Last Updated : 14 Jun, 2022
View Discussion
Improve Article
Save Article

Given an integer N, find the number of natural numbers less than or equal to N and have 4 factors.

Example: 

Input: N = 8
Output: 2
Explanation: {1} is divisor set of 1
{1, 2} is divisor set of 2
{1, 3} is divisor set of 3
{1, 2, 4} is divisor set of 4
{1, 5} is divisor set of 5
{1, 2, 3, 6} is divisor set of 6
{1, 7} is divisor set of 7
{1, 2, 4, 8} is divisor set of 8
So, 6 and 8 are only natural numbers less than or equal to N and count of divisors 4.

Input: N = 2
Output: 0

 

Approach: The idea to solve the problem is based on the following observation:

  • Any number M can be written in form M = p1e1 * p2e2 *  . . . where (p1, p2 . . .) are primes and (e1, e2 . . .) are respective exponents.
  • The total number of factors of M is therefore (e + 1)*(e + 1)* . . .
  • From above points, for the count of divisors of a natural number to be 4, there are two cases:-
    • Case-1: N = p1 * p2 (where p1 and p2 are two distinct prime numbers)
    • Case-2: N = p3 (where p is a prime number)
  • So there must be two primes whose multiplication is less than N or one prime whose cube is less than N.

Follow the steps mentioned below to solve the problem:

  • Find all the prime numbers less than or equal to N using the sieve of Eratosthenes.
  • For Case-1 iterate through all prime numbers and use binary search to find a number of primes whose product is at most N.
  • For Case-2, do a binary search to find the number of primes whose cube is less than or equal to N.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find primes <= N
vector<int> SieveOfEratosthenes(int n)
{
    // Create a boolean array
    // "prime[0..n]" and initialize
    // all entries it as true.
    // A value in prime[i] will
    // finally be false if i is
    // Not a prime, else true.
    bool prime[n + 1];
    memset(prime, true, sizeof(prime));
 
    for (long long int p = 2;
         p * p <= n; p++) {
 
        // If prime[p] is not changed,
        // then it is a prime
        if (prime[p] == true) {
            // Update all multiples
            // of p greater than or
            // equal to the square of it
            for (long long int i = p * p;
                 i <= n; i += p)
                prime[i] = false;
        }
    }
 
    // Vector for storing prime number
    // less than or equal to N
    vector<int> primes;
 
    // Store all prime numbers
    for (int p = 2; p <= n; p++)
        if (prime[p])
            primes.push_back(p);
 
    return primes;
}
 
// Find floor of cube root of N
int primeCubic(vector<int>& primes, int N)
{
 
    // Val stores cube root of N
    long long int l = 0, r = N, mid, val;
 
    // Binary search loop for finding
    // floor of cube root of N
    while (l <= r) {
        mid = (l + r) / 2;
        if ((mid * mid * mid) <= N) {
            val = mid;
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }
    }
 
    // Iterator for finding index with
    // value just greater than Val in primes
    auto it = upper_bound(primes.begin(),
                          primes.end(), val);
    it--;
 
    return (it - primes.begin() + 1);
}
 
// Function to find primes with product <= N
int primeProduct(vector<int>& primes,
                 int N)
{
    // Stores the answer
    int answer = 0;
 
    // Iterator storing pointer to
    // current prime
    auto cur = primes.begin();
 
    // Loop for traversing all primes
    // Find number of indices less than
    // current indices for which product
    // is less than or equal to N
    for (auto i : primes) {
        long long int add
            = upper_bound(primes.begin(),
                          cur, (N / i))
              - primes.begin();
        answer += add;
        cur++;
    }
    return answer;
}
 
// Function to find the total count
int print(int N)
{
    vector<int> primes
        = SieveOfEratosthenes(N);
 
    int answer = 0;
    answer += primeCubic(primes, N);
    answer += primeProduct(primes, N);
    return answer;
}
 
// Driver code
int main()
{
    int N = 8;
 
    // Print function Call
    cout << print(N);
    return 0;
}


Python3




# Python3 program for the above approach
import bisect
 
# Function to find primes <= N
def SieveOfEratosthenes(n):
 
    # Create a boolean array
    # "prime[0..n]" and initialize
    # all entries it as true.
    # A value in prime[i] will
    # finally be false if i is
    # Not a prime, else true.
    prime = [True] * (n + 1)
     
    for p in range(2, 1 + int(n ** 0.5)):
         
        # If prime[p] is not changed,
        # then it is a prime
        if (prime[p] == True):
            # Update all multiples
            # of p greater than or
            # equal to the square of it
            for i in range(p * p, n + 1, p):
                prime[i] = False
 
    # Vector for storing prime number
    # less than or equal to N
    primes = []
 
    # Store all prime numbers
    for p in range(2, n + 1):
        if prime[p]:
            primes.append(p)
 
 
    return primes
 
 
# Find floor of cube root of N
def primeCubic(primes, N):
 
    #Val stores cube root of N
    l = 0
    r = N
 
    # Binary search loop for finding
    # floor of cube root of N
    while (l <= r):
        mid = (l + r) // 2
        if ((mid * mid * mid) <= N):
            val = mid
            l = mid + 1
         
        else:
            r = mid - 1
 
    # Iterator for finding index with
    # value just greater than Val in primes
    it = bisect.bisect_right(primes, val)
 
    return it
 
# Function to find primes with product <= N
def primeProduct(primes, N):
 
    # Stores the answer
    answer = 0
 
    # Iterator storing pointer to
    # current prime
    cur = 0
 
    # Loop for traversing all primes
    # Find number of indices less than
    # current indices for which product
    # is less than or equal to N
    for i in primes:
        add = bisect.bisect_right(primes[:cur], N // i)
        answer += add
        cur += 1
 
    return answer
 
# Function to find the total count
def print_(N):
 
    primes = SieveOfEratosthenes(N)
 
    answer = 0
    answer += primeCubic(primes, N)
    answer += primeProduct(primes, N)
    return answer
 
 
# Driver code
N = 8
 
# Print function Call
print(print_(N))
 
# This code is contributed by phasing17


Output

2

Time Complexity: O(N * log(logN) + N + logN) ≈ O(N * log (logN))
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!