Count of numbers up to N having only 4 factors or divisors
Last Updated :
17 Dec, 2023
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
Naive Approach:
The naive approach for the problem is that we can traverse from 1 to N and count number of divisors of each one of them. If the count comes out to be 4 , then increase the resultant number say res by 1. Finally at the end of traversal we will be having the number of natural numbers less than or equal to N and have 4 factors in the variable res.
We will be counting divisors efficiently using the approach of complexity O(n1/3) as mentioned and discussed in this article: Count Divisors of n in O(n^1/3).
Algorithm:
- Define a function SieveOfEratosthenes that accepts n, a boolean array prime[], a boolean array primesquare[], and an integer array a[] as parameters.
- Initialize all entries in prime[] as true and all entries in primesquare[] as false.
- Mark prime[1] as false.
- Use the Sieve of Eratosthenes algorithm to mark all non-prime numbers in the range 2 to n in the prime[] array.
- Store all prime numbers in the range 2 to n in the integer array a[].
- For each prime number p in the integer array a[], update the primesquare[p*p] to true.
- Define a function countDivisors that accepts an integer n as a parameter.
- If n is 1, return 1 as it will have only 1 as a factor.
- Declare a boolean array prime[] and primesquare[] of size n+1 and n*n+1 respectively.
- Declare an integer array a[] of size n.
- Call the SieveOfEratosthenes function with parameters n, prime[], primesquare[], and a[].
- Initialize a variable ans to 1 that will contain the total number of distinct divisors.
- Loop through all prime numbers a[i] in the integer array a[] until a[i]^3 > n.
- Calculate the power of a[i] in n using a while loop, incrementing the power for each iteration until n is no longer divisible by a[i].
- Multiply ans by (cnt+1) where cnt is the power of a[i] in n.
- If n is greater than 1 after the loop, then it has a prime factor greater than cube root of n, which will have a power of 1. Multiply ans by 2 in this case.
- If n is a square of a prime number, multiply ans by 3.
- If n is not equal to 1 after the above cases, it means n has two distinct prime factors. Multiply ans by 4 in this case.
- Return ans.
- Define the main function.
- Initialize an integer N to the maximum range.
- Initialize an integer variable res to 0 that will store the result.
- Loop through each number from 1 to N.
- If the count of divisors of the current number is 4, increment res by 1.
- Print the value of res as the result.
Below is the implementation of the approach:
C++
#include <bits/stdc++.h>
using namespace std;
void SieveOfEratosthenes( int n, bool prime[],
bool primesquare[], int a[])
{
for ( int i = 2; i <= n; i++)
prime[i] = true ;
for ( int i = 0; i <= (n * n + 1); i++)
primesquare[i] = false ;
prime[1] = false ;
for ( int p = 2; p * p <= n; p++) {
if (prime[p] == true ) {
for ( int i = p * p; i <= n; i += p)
prime[i] = false ;
}
}
int j = 0;
for ( int p = 2; p <= n; p++) {
if (prime[p]) {
a[j] = p;
primesquare[p * p] = true ;
j++;
}
}
}
int countDivisors( int n) {
if (n == 1)
return 1;
bool prime[n + 1], primesquare[n * n + 1];
int a[n];
SieveOfEratosthenes(n, prime, primesquare, a);
int ans = 1;
for ( int i = 0;; i++) {
if (a[i] * a[i] * a[i] > n)
break ;
int cnt = 1;
while (n % a[i] == 0)
{
n = n / a[i];
cnt = cnt + 1;
}
ans = ans * cnt;
}
if (prime[n])
ans = ans * 2;
else if (primesquare[n])
ans = ans * 3;
else if (n != 1)
ans = ans * 4;
return ans;
}
int main() {
int N = 8;
int res = 0;
for ( int i = 1; i <= N; i++) {
if ( countDivisors(i) == 4)
res += 1;
}
cout<< res << endl;
return 0;
}
|
Java
import java.util.Arrays;
class Solution {
static boolean [] prime;
static boolean [] primesquare;
public static int [] sieveOfEratosthenes( int n)
{
prime = new boolean [n + 1 ];
Arrays.fill(prime, true );
primesquare = new boolean [(n * n) + 1 ];
Arrays.fill(primesquare, false );
int [] a = new int [n];
prime[ 1 ] = false ;
int p = 2 ;
while (p * p <= n) {
if (prime[p]) {
for ( int i = p * p; i <= n; i += p) {
prime[i]
= false ;
}
}
p++;
}
int j = 0 ;
for (p = 2 ; p <= n; p++) {
if (prime[p]) {
a[j] = p;
primesquare[p * p]
= true ;
j++;
}
}
return a;
}
public static int countDivisors( int n)
{
if (n == 1 ) {
return 1 ;
}
int [] a = sieveOfEratosthenes(n);
int ans = 1 ;
int i = 0 ;
while ( true ) {
if (a[i] * a[i] * a[i] > n) {
break ;
}
int cnt = 1 ;
while (n % a[i] == 0 ) {
n = n / a[i];
cnt++;
}
ans *= cnt;
i++;
}
if (n > 1 ) {
if (prime[n]) {
ans *= 2 ;
}
else if (primesquare[n]) {
ans *= 3 ;
}
else {
ans *= 4 ;
}
}
return ans;
}
public static void main(String[] args)
{
int N = 8 ;
int res = 0 ;
for ( int i = 1 ; i <= N; i++) {
if (countDivisors(i) == 4 ) {
res++;
}
}
System.out.println(res);
}
}
|
Python3
def SieveOfEratosthenes(n):
prime = [ True ] * (n + 1 )
primesquare = [ False ] * ((n * n) + 1 )
a = [ 0 ] * n
prime[ 1 ] = False
p = 2
while p * p < = n:
if prime[p]:
for i in range (p * p, n + 1 , p):
prime[i] = False
p + = 1
j = 0
for p in range ( 2 , n + 1 ):
if prime[p]:
a[j] = p
primesquare[p * p] = True
j + = 1
return a, prime, primesquare
def countDivisors(n):
if n = = 1 :
return 1
a, prime, primesquare = SieveOfEratosthenes(n)
ans = 1
i = 0
while True :
if a[i] * a[i] * a[i] > n:
break
cnt = 1
while n % a[i] = = 0 :
n = n / / a[i]
cnt + = 1
ans * = cnt
i + = 1
if prime[n]:
ans * = 2
elif primesquare[n]:
ans * = 3
elif n ! = 1 :
ans * = 4
return ans
def main():
N = 8
res = 0
for i in range ( 1 , N + 1 ):
if countDivisors(i) = = 4 :
res + = 1
print (res)
if __name__ = = "__main__" :
main()
|
C#
using System;
class GFG
{
static bool [] prime;
static bool [] primesquare;
public static int [] SieveOfEratosthenes( int n)
{
prime = new bool [n + 1];
Array.Fill(prime, true );
primesquare = new bool [(n * n) + 1];
Array.Fill(primesquare, false );
int [] a = new int [n];
prime[1] = false ;
int p = 2;
while (p * p <= n)
{
if (prime[p])
{
for ( int i = p * p; i <= n; i += p)
{
prime[i] = false ;
}
}
p++;
}
int j = 0;
for (p = 2; p <= n; p++)
{
if (prime[p])
{
a[j] = p;
primesquare[p * p] = true ;
j++;
}
}
return a;
}
public static int CountDivisors( int n)
{
if (n == 1)
{
return 1;
}
int [] a = SieveOfEratosthenes(n);
int ans = 1;
int i = 0;
while ( true )
{
if (a[i] * a[i] * a[i] > n)
{
break ;
}
int cnt = 1;
while (n % a[i] == 0)
{
n = n / a[i];
cnt++;
}
ans *= cnt;
i++;
}
if (n > 1)
{
if (prime[n])
{
ans *= 2;
}
else if (primesquare[n])
{
ans *= 3;
}
else
{
ans *= 4;
}
}
return ans;
}
public static void Main()
{
int N = 8;
int res = 0;
for ( int i = 1; i <= N; i++)
{
if (CountDivisors(i) == 4)
{
res++;
}
}
Console.WriteLine(res);
}
}
|
Javascript
let primesquare;
function sieveOfEratosthenes(n)
{
let prime = new Array(n + 1).fill( true );
primesquare = new Array((n * n) + 1).fill( false );
let a = [];
prime[1] = false ;
let p = 2;
while (p * p <= n) {
if (prime[p]) {
for (let i = p * p; i <= n; i += p) {
prime[i] = false ;
}
}
p++;
}
let j = 0;
for (p = 2; p <= n; p++) {
if (prime[p]) {
a[j] = p;
primesquare[p * p]
= true ;
j++;
}
}
return a;
}
function countDivisors(n)
{
if (n == 1) {
return 1;
}
let a = sieveOfEratosthenes(n);
let ans = 1;
let i = 0;
while ( true ) {
if (a[i] * a[i] * a[i] > n) {
break ;
}
let cnt = 1;
while (n % a[i] == 0) {
n = n / a[i];
cnt++;
}
ans *= cnt;
i++;
}
if (n > 1) {
if (a.includes(n)) {
ans *= 2;
}
else if (primesquare[n]) {
ans *= 3;
}
else {
ans *= 4;
}
}
return ans;
}
let N = 8;
let res = 0;
for (let i = 1; i <= N; i++) {
if (countDivisors(i) == 4) {
res++;
}
}
console.log(res);
|
Time Complexity: O(N * N1/3) as for loop which is running contributes O(N) and inside it countDivisors function contributes N1/3 time. So, overall time complexity becomes O(N * N1/3). Here, N is the input integer.
Auxiliary Space: O(N) as arrays like prime and primesquare has been created. Here, N is the input integer.
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++
#include <bits/stdc++.h>
using namespace std;
vector< int > SieveOfEratosthenes( int n)
{
bool prime[n + 1];
memset (prime, true , sizeof (prime));
for ( long long int p = 2;
p * p <= n; p++) {
if (prime[p] == true ) {
for ( long long int i = p * p;
i <= n; i += p)
prime[i] = false ;
}
}
vector< int > primes;
for ( int p = 2; p <= n; p++)
if (prime[p])
primes.push_back(p);
return primes;
}
int primeCubic(vector< int >& primes, int N)
{
long long int l = 0, r = N, mid, val;
while (l <= r) {
mid = (l + r) / 2;
if ((mid * mid * mid) <= N) {
val = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
auto it = upper_bound(primes.begin(),
primes.end(), val);
it--;
return (it - primes.begin() + 1);
}
int primeProduct(vector< int >& primes,
int N)
{
int answer = 0;
auto cur = primes.begin();
for ( auto i : primes) {
long long int add
= upper_bound(primes.begin(),
cur, (N / i))
- primes.begin();
answer += add;
cur++;
}
return answer;
}
int print( int N)
{
vector< int > primes
= SieveOfEratosthenes(N);
int answer = 0;
answer += primeCubic(primes, N);
answer += primeProduct(primes, N);
return answer;
}
int main()
{
int N = 8;
cout << print(N);
return 0;
}
|
Java
import java.util.*;
public class Solution
{
static ArrayList<Integer> SieveOfEratosthenes( int n)
{
boolean [] prime = new boolean [n + 1 ];
Arrays.fill(prime, true );
for ( int p = 2 ; p * p <= n; p++) {
if (prime[p] == true ) {
for ( int i = p * p; i <= n; i += p)
prime[i] = false ;
}
}
ArrayList<Integer> primes = new ArrayList<>();
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();
int low = lo;
int high = hi;
while (low < high && low != N) {
mid = low + (high - low) / 2 ;
if (key >= arr.get(mid)) {
low = mid + 1 ;
}
else {
high = mid;
}
}
return low;
}
static int primeCubic(ArrayList<Integer> primes, int N)
{
int l = 0 , r = N, mid, val = 0 ;
while (l <= r) {
mid = (l + r) / 2 ;
if ((mid * mid * mid) <= N) {
val = mid;
l = mid + 1 ;
}
else {
r = mid - 1 ;
}
}
int it = upper_bound(primes, 0 , primes.size(), val);
it--;
return (it + 1 );
}
static int primeProduct(ArrayList<Integer> primes,
int N)
{
int answer = 0 ;
int cur = 0 ;
for ( int i : primes) {
int add = upper_bound(primes, 0 , cur, (N / i));
answer += add;
cur++;
}
return answer;
}
static int print( int N)
{
ArrayList<Integer> primes = SieveOfEratosthenes(N);
int answer = 0 ;
answer += primeCubic(primes, N);
answer += primeProduct(primes, N);
return answer;
}
public static void main(String[] args)
{
int N = 8 ;
System.out.println(print(N));
}
}
|
Python3
import bisect
def SieveOfEratosthenes(n):
prime = [ True ] * (n + 1 )
for p in range ( 2 , 1 + int (n * * 0.5 )):
if (prime[p] = = True ):
for i in range (p * p, n + 1 , p):
prime[i] = False
primes = []
for p in range ( 2 , n + 1 ):
if prime[p]:
primes.append(p)
return primes
def primeCubic(primes, N):
l = 0
r = N
while (l < = r):
mid = (l + r) / / 2
if ((mid * mid * mid) < = N):
val = mid
l = mid + 1
else :
r = mid - 1
it = bisect.bisect_right(primes, val)
return it
def primeProduct(primes, N):
answer = 0
cur = 0
for i in primes:
add = bisect.bisect_right(primes[:cur], N / / i)
answer + = add
cur + = 1
return answer
def print_(N):
primes = SieveOfEratosthenes(N)
answer = 0
answer + = primeCubic(primes, N)
answer + = primeProduct(primes, N)
return answer
N = 8
print (print_(N))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int [] SieveOfEratosthenes( int n)
{
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] == true ) {
for ( int i = p * p; i <= n; i += p)
prime[i] = false ;
}
}
List< int > primes = new List< int >();
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;
}
static int primeCubic( int [] primes, int N)
{
int l = 0, r = N, mid, val = 0;
while (l <= r) {
mid = (l + r) / 2;
if ((mid * mid * mid) <= N) {
val = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
int it = upper_bound(primes, primes.Length, val);
return it;
}
static int primeProduct( int [] primes, int N)
{
int answer = 0;
int cur = 0;
for ( int i = 0; i < primes.Length; i++) {
int add
= upper_bound(primes, cur, (N / primes[i]));
answer += add;
cur++;
}
return answer;
}
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;
Console.Write(print(N));
}
}
|
Javascript
const SieveOfEratosthenes = (n) => {
let prime = Array(n + 1).fill( true );
for (let p = 2; p * p <= n; p++)
{
if (prime[p])
{
for (let i = p * p; i <= n; i += p)
prime[i] = false ;
}
}
let primes = [];
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;
let low = lo;
let high = hi;
while (low < high && low != N) {
mid = low + Math.floor((high - low) / 2);
if (key >= arr[mid]) {
low = mid + 1;
}
else {
high = mid;
}
}
return low;
}
const primeCubic = (primes, N) => {
let l = 0, r = N, mid, val = 0;
while (l <= r) {
mid = Math.floor((l + r) / 2);
if ((mid * mid * mid) <= N) {
val = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
let it = upper_bound(primes, 0, primes.length, val);
it--;
return (it + 1);
}
const primeProduct = (primes, N) => {
let answer = 0;
let cur = 0;
for (let i of primes) {
let add = upper_bound(primes, 0, cur, Math.floor(N / i));
answer += add;
cur++;
}
return answer;
}
const print = (N) => {
let primes = SieveOfEratosthenes(N);
let answer = 0;
answer += primeCubic(primes, N);
answer += primeProduct(primes, N);
return answer;
}
console.log(print(8));
|
Time Complexity: O(N * log(logN) + N + logN) ≈ O(N * log (logN))
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...