Skip to content
Related Articles
Open in App
Not now

Related Articles

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

Improve Article
Save Article
Like Article
  • Last Updated : 07 Feb, 2023
Improve Article
Save Article
Like 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;
}

Java




// Java program for above approach
import java.util.*;
 
public class Solution
{
 
  // Function to find primes <= N
  static ArrayList<Integer> 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.
    boolean[] prime = new boolean[n + 1];
    Arrays.fill(prime, true);
 
    for (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 (int i = p * p; i <= n; i += p)
          prime[i] = false;
      }
    }
 
    // Vector for storing prime number
    // less than or equal to N
    ArrayList<Integer> primes = new ArrayList<>();
 
    // Store all prime numbers
    for (int p = 2; p <= n; p++)
      if (prime[p])
        primes.add(p);
 
    return primes;
  }
 
  static int upper_bound(ArrayList<Integer> arr, int lo,
                         int hi, int key)
  {
    int mid, N = arr.size();
 
    // Initialise starting index and
    // ending index
    int low = lo;
    int high = hi;
 
    // Till low is less than high
    while (low < high && low != N) {
      mid = low + (high - low) / 2;
 
      // If key is greater than or equal
      // to arr[mid], then find in
      // right subarray
      if (key >= arr.get(mid)) {
        low = mid + 1;
      }
 
      // If key is less than arr[mid]
      // then find in left subarray
      else {
        high = mid;
      }
    }
    return low;
  }
  // Find floor of cube root of N
  static int primeCubic(ArrayList<Integer> primes, int N)
  {
 
    // Val stores cube root of N
    int l = 0, r = N, mid, val = 0;
 
    // 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
    int it = upper_bound(primes, 0, primes.size(), val);
    it--;
 
    return (it + 1);
  }
 
  // Function to find primes with product <= N
  static int primeProduct(ArrayList<Integer> primes,
                          int N)
  {
    // Stores the answer
    int answer = 0;
 
    // Iterator storing pointer to
    // current prime
    int 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 (int i : primes) {
      int add = upper_bound(primes, 0, cur, (N / i));
      answer += add;
      cur++;
    }
    return answer;
  }
 
  // Function to find the total count
  static int print(int N)
  {
    ArrayList<Integer> primes = SieveOfEratosthenes(N);
 
    int answer = 0;
    answer += primeCubic(primes, N);
    answer += primeProduct(primes, N);
    return answer;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 8;
     
    // Print function Call
    System.out.println(print(N));
  }
}
 
// This code is contributed by karandeep1234.

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

C#




using System;
using System.Collections.Generic;
class GFG
{
   
  // Function to find primes <= N
  static 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 = new bool[n + 1];
    for (int i = 0; i <= n; i++) {
      prime[i] = true;
    }
 
    for (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 (int i = p * p; i <= n; i += p)
          prime[i] = false;
      }
    }
 
    // Array for storing prime number
    // less than or equal to N
    // int []primes= new int[];
    List<int> primes = new List<int>();
     
    // Store all prime numbers
    for (int p = 2; p <= n; p++)
      if (prime[p])
        primes.Add(p);
 
    return primes.ToArray();
  }
 
  static int upper_bound(int[] arr, int N, int X)
  {
    int mid;
    int low = 0;
    int high = N;
    while (low < high) {
      mid = low + (high - low) / 2;
      if (X >= arr[mid])
        low = mid + 1;
      else
        high = mid;
    }
    if (low < N && arr[low] <= X)
      low++;
    return low;
  }
   
  // Find floor of cube root of N
  static int primeCubic(int[] primes, int N)
  {
 
    // Val stores cube root of N
    int l = 0, r = N, mid, val = 0;
 
    // 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
    int it = upper_bound(primes, primes.Length, val);
    return it;
  }
   
  // Function to find primes with product <= N
  static int primeProduct(int[] primes, int N)
  {
     
    // Stores the answer
    int answer = 0;
     
    // Iterator storing pointer to
    // current prime
    int 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 (int i = 0; i < primes.Length; i++) {
      int add
        = upper_bound(primes, cur, (N / primes[i]));
      answer += add;
      cur++;
    }
    return answer;
  }
 
  // Function to find the total count
  static int print(int N)
  {
    int[] primes = SieveOfEratosthenes(N);
 
    int answer = 0;
    answer += primeCubic(primes, N);
    answer += primeProduct(primes, N);
    return answer;
  }
  static void Main()
  {
    int N = 8;
 
    // Print function Call
    Console.Write(print(N));
  }
}
 
// This code is contributed by garg28harsh.

Javascript




// Function to find primes <=N
const 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.
  let prime = Array(n + 1).fill(true);
  for (let p = 2; p * p <= n; p++)
  {
   
      // If prime[p] is not changed,
      // then it is a prime
    if (prime[p])
    {
     
      // Update all multiples
      // of p greater than or
      // equal to the square of it
      for (let i = p * p; i <= n; i += p)
        prime[i] = false;
    }
  }
   
// Vector for storing prime number
// less than or equal to N
  let primes = [];
   
// Store all prime numbers
  for (let p = 2; p <= n; p++)
    if (prime[p])
      primes.push(p);
 
  return primes;
}
 
const upper_bound = (arr, lo, hi, key) => {
  let mid, N = arr.length;
   
// Initialise starting index and
// ending index
  let low = lo;
  let high = hi;
   
// Till low is less than high
  while (low < high && low != N) {
    mid = low + Math.floor((high - low) / 2);
     
    // If key is greater than or equal
      // to arr[mid], then find in
      // right subarray
    if (key >= arr[mid]) {
      low = mid + 1;
    }
     
    // If key is less than arr[mid]
    // then find in left subarray
    else {
      high = mid;
    }
  }
  return low;
}
 
// Find floor of cube root of N
const primeCubic = (primes, N) => {
 
  // Val stores cube root of N
  let l = 0, r = N, mid, val = 0;
   
 // Binary search loop for finding
    // floor of cube root of N
  while (l <= r) {
    mid = Math.floor((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
  let it = upper_bound(primes, 0, primes.length, val);
  it--;
 
  return (it + 1);
}
 
 // Function to find primes with product <= N
const primeProduct = (primes, N) => {
  let answer = 0;
   
    // Iterator storing pointer to
    // current prime
  let 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 (let i of primes) {
    let add = upper_bound(primes, 0, cur, Math.floor(N / i));
    answer += add;
    cur++;
  }
  return answer;
}
 
// Function to find the total count
const print = (N) => {
  let primes = SieveOfEratosthenes(N);
 
  let answer = 0;
  answer += primeCubic(primes, N);
  answer += primeProduct(primes, N);
  return answer;
}
 
console.log(print(8));
 
// This code is contributed by anskalyan3.

Output

2

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


My Personal Notes arrow_drop_up
Like Article
Save Article
Related Articles

Start Your Coding Journey Now!