Count numbers up to N having exactly 5 divisors
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 |
2
Time Complexity: O(N*log N)
Auxiliary Space: O(N)