Skip to content
Related Articles

Related Articles

Count numbers up to N having exactly 5 divisors

View Discussion
Improve Article
Save Article
  • Last Updated : 19 May, 2021

Given a positive integer N, the task is to count the number of integers from the range [1, N] having exactly 5 divisors.

Examples:

Input: N = 18
Output: 1
Explanation:
From all the integers over the range [1, 18], 16 is the only integer that has exactly 5 divisors, i.e. 1, 2, 8, 4 and 16.
Therefore, the count of such integers is 1.

Input: N = 100
Output: 2

Naive Approach: The simplest approach to solve the given problem is to iterate over the range [1, N] and count those integers in this range having the count of divisors as 5
Time Complexity: O(N4/3)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by observing a fact that the numbers that have exactly 5 divisors can be expressed in the form of p4, where p is a prime number as the count of divisors is exactly 5. Follow the below steps to solve the problem:

  • Generate all primes such that their fourth power is less than 1018  by using Sieve of Eratosthenes and store it in vector, say A[].
  • Initialize two variables, say low as 0 and high as A.size() – 1.
  • For performing the Binary Search iterate until low is less than high and perform the following steps:
    • Find the value of mid as the (low + high)/2.
    • Find the value of fourth power of element at indices mid (mid – 1) and store it in a variable, say current and previous respectively.
    • If the value of current is N, then print the value of A[mid] as the result.
    • If the value of current is greater than N and previous is at most N, then print the value of A[mid] as the result.
    • If the value of current is greater than N then update the value of high as (mid – 1). Otherwise, update the value of low as (mid + 1).

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
#define ll long long int
const int MAX = 1e5;
using namespace std;
 
// Function to calculate the value of
// (x^y) using binary exponentiation
ll power(ll x, unsigned ll y)
{
    // Stores the value of x^y
    ll res = 1;
 
    // Base Case
    if (x == 0)
        return 0;
 
    while (y > 0) {
 
        // If y is odd multiply
        // x with result
        if (y & 1)
            res = (res * x);
 
        // Otherwise, divide y by 2
        y = y >> 1;
 
        x = (x * x);
    }
    return res;
}
 
// Function to perform the Sieve Of
// Eratosthenes to find the prime
// number over the range [1, 10^5]
void SieveOfEratosthenes(
    vector<pair<ll, ll> >& v)
{
    bool prime[MAX + 1];
 
    memset(prime, true, sizeof(prime));
 
    prime[1] = false;
 
    for (int p = 2; p * p <= MAX; p++) {
 
        // If prime[p] is not changed
        // then it is a prime
        if (prime[p] == true) {
 
            // Set all the multiples of
            // p to non-prime
            for (int i = p * 2;
                 i <= MAX; i += p)
                prime[i] = false;
        }
    }
 
    int num = 1;
 
    // Iterate over the range [1, MAX]
    for (int i = 1; i <= MAX; i++) {
 
        // Store all the prime number
        if (prime[i]) {
            v.push_back({ i, num });
            num++;
        }
    }
}
 
// Function to find the primes having
// only 5 divisors
int countIntegers(ll n)
{
    // Base Case
    if (n < 16) {
        return 0;
    }
 
    // First value of the pair has the
    // prime number and the second value
    // has the count of primes till that
    // prime numbers
    vector<pair<ll, ll> > v;
 
    // Precomputing all the primes
    SieveOfEratosthenes(v);
 
    int low = 0;
    int high = v.size() - 1;
 
    // Perform the Binary search
    while (low <= high) {
 
        int mid = (low + high) / 2;
 
        // Calculate the fourth power of
        // the curr and prev
        ll curr = power(v[mid].first, 4);
        ll prev = power(v[mid - 1].first, 4);
 
        if (curr == n) {
 
            // Return value of mid
            return v[mid].second;
        }
 
        else if (curr > n and prev <= n) {
 
            // Return value of mid-1
            return v[mid - 1].second;
        }
        else if (curr > n) {
 
            // Update the value of high
            high = mid - 1;
        }
 
        else {
 
            // Update the value of low
            low = mid + 1;
        }
    }
    return 0;
}
 
// Driver Code
int main()
{
    ll N = 100;
    cout << countIntegers(N);
 
    return 0;
}

Java




// Java program for the above approach
import java.util.Vector;
 
public class GFG {
    static int MAX = (int)1e5;
 
    public static class pair {
        long first;
        long second;
        pair(long first, long second)
        {
            this.first = first;
            this.second = second;
        }
    }
    // Function to calculate the value of
    // (x^y) using binary exponentiation
    static long power(long x, long y)
    {
       
        // Stores the value of x^y
        long res = 1;
 
        // Base Case
        if (x == 0)
            return 0;
 
        while (y > 0)
        {
 
            // If y is odd multiply
            // x with result
            if ((y & 1) == 1)
                res = (res * x);
 
            // Otherwise, divide y by 2
            y = y >> 1;
 
            x = (x * x);
        }
        return res;
    }
 
    // Function to perform the Sieve Of
    // Eratosthenes to find the prime
    // number over the range [1, 10^5]
    static void SieveOfEratosthenes(Vector<pair> v)
    {
        boolean prime[] = new boolean[MAX + 1];
 
        for (int i = 0; i < prime.length; i++) {
            prime[i] = true;
        }
 
        prime[1] = false;
 
        for (int p = 2; p * p <= MAX; p++) {
 
            // If prime[p] is not changed
            // then it is a prime
            if (prime[p] == true) {
 
                // Set all the multiples of
                // p to non-prime
                for (int i = p * 2; i <= MAX; i += p)
                    prime[i] = false;
            }
        }
 
        int num = 1;
 
        // Iterate over the range [1, MAX]
        for (int i = 1; i <= MAX; i++) {
 
            // Store all the prime number
            if (prime[i]) {
                v.add(new pair(i, num));
                num++;
            }
        }
    }
 
    // Function to find the primes having
    // only 5 divisors
    static long countIntegers(long n)
    {
        // Base Case
        if (n < 16) {
            return 0;
        }
 
        // First value of the pair has the
        // prime number and the second value
        // has the count of primes till that
        // prime numbers
        Vector<pair> v = new Vector<>();
 
        // Precomputing all the primes
        SieveOfEratosthenes(v);
 
        int low = 0;
        int high = v.size() - 1;
 
        // Perform the Binary search
        while (low <= high) {
 
            int mid = (low + high) / 2;
 
            // Calculate the fourth power of
            // the curr and prev
            long curr = power(v.get(mid).first, 4);
            long prev = power(v.get(mid - 1).first, 4);
 
            if (curr == n) {
 
                // Return value of mid
                return v.get(mid).second;
            }
 
            else if (curr > n && prev <= n) {
 
                // Return value of mid-1
                return v.get(mid - 1).second;
            }
            else if (curr > n) {
 
                // Update the value of high
                high = mid - 1;
            }
 
            else {
 
                // Update the value of low
                low = mid + 1;
            }
        }
        return 0;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        long N = 100;
        System.out.println(countIntegers(N));
    }
}
 
// This code is contributed by abhinavjain194

Output: 

2

 

Time Complexity: O(N*log N)
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!