Open In App

Find minimum number K such that its factorial is multiple of N

Last Updated : 10 Aug, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer N. The task is to find minimum K such that the factorial of K is multiple of N. (2 &#x2264 N &#x2264 1012)

Examples:

Input: N = 30
Output: 5
Explanation: 5! % 30 = 120 % 30 = 0, Therefore 5 is the answer

Input: N = 280
Output: 7

Approach: To solve the problem follow the below idea:

  • Binary Search can be used to solve this problem. Number of times number X! can be divided by Y is Z (for example 8 can be divided by 2, three times), Z = (X / Y) + (X / Y2) + (X / Y3) + (X / Y4) + ……………
  • The idea is to first find all the prime divisors of N and their powers using a map data structure. Then, perform binary search to find the minimum value of K such that K! is a multiple of N and check if the mid value satisfies the condition or not by checking if every number that divides N compared with the mid value also divides mid, using the above formula. 
  • If the number of times N is divided by a prime divisor is greater than mid factorial, then mid factorial is not divisible by N, and return false else, returns true.

Below are the steps for the above approach:

  • Declaring Hashmap mp[] to store divisors and their powers for number N.
  • Declare low and high variables initially with values 2 and 1013.
  • Write test() function that takes one parameter and returns a bool value whether the given number’s factorial is divisible by N.
  • In the test, the function iterates all divisors of number N and checks whether those divisors also divide mid factorial which can be checked using the above number theory formula.
  • Initialize the mid variable, mid = (low + high) / 2.
  • Run a while loop till high – low > 1.
  • check if the test function for the given mid value is true or not.
  • if true set high to mid.
  • else set low to mid + 1.
  • After the while loop ends if the test function for low is true then return low else return high as the answer.

Below is the code for the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// To avoid overflow
#define int long long
 
// Check function of binary search
bool test(int mid, map<int, int>& mp)
{
 
    // Every number that divides N
    // compared with Mid whether it
    // also divides Mid
    for (auto& e : mp) {
 
        // cnt stores number of times mid
        // factorial can be divided with
        // e.first (which is number that
        // also divides N e.second times)
        int cnt = 0;
 
        // Iterating till power of 30
        for (int i = 1; i <= 30; i++) {
 
            // Number theory formula
            int temp = (mid / pow(e.first, i));
 
            // If temp is zero we can
            // break it out to speed
            // up the program
            if (temp == 0)
                break;
 
            // Adding temp to count
            cnt += temp;
        }
 
        // If number of times N is divided
        // by e.first greater than mid
        // factorial that means mid factorial
        // is not divisible by N return false
        if (e.second > cnt)
            return 0;
    }
 
    // Otherwise return true
    return 1;
}
 
// Function to find minimum value of K
// such that K! is multiple of N
int findMinK(int N)
{
 
    // Step 1 : Finding all prime divisors
    // of N and their powers
    // Hash map to store prime divisors
    // with its powers
    map<int, int> mp;
 
    // Count the number of times 2 divides
    int count = 0;
    while (!(N % 2)) {
 
        // N divide by 2
        N /= 2;
 
        // Increasing the counter
        count++;
    }
 
    // If 2 divides it
    if (count)
        mp[2] = count;
 
    // Check for all the possible numbers
    // that can divide it
    for (int i = 3; i <= sqrt(N); i += 2) {
 
        // Resetting count to zero
        count = 0;
 
        // Divide it until possible
        while (N % i == 0) {
 
            // Increasing the counter
            count++;
 
            // Divide it by i
            N = N / i;
        }
 
        // If count is non zero then
        if (count)
            mp[i] = count;
    }
 
    // If n at the end is a prime number.
    if (N > 2)
        mp[N] = 1;
 
    // Step 2 : Binary Search on answer K
    // low pointer on 2 and high on
    // maximum value
    int low = 2, high = 1e13;
 
    // While high is greater than to 1
    while (high - low > 1) {
 
        // mid value
        int mid = (high + low) / 2;
 
        // Checking for mid value
        if (test(mid, mp)) {
            high = mid;
        }
        else {
            low = mid + 1;
        }
    }
 
    // If check fucntion is true for
    // low then return low
    if (test(low, mp))
        return low;
 
    // Else return high
    else
        return high;
}
 
// Driver Code
int32_t main()
{
 
    // Input 1
    int N = 30;
 
    // Function Call
    cout << findMinK(N) << endl;
 
    return 0;
}


Java




// Java code to implement the approach
import java.util.*;
 
class GFG {
 
    // To avoid overflow
    static long MAX_VALUE = (long)1e13;
 
    // Check function of binary search
    static boolean test(long mid, Map<Long, Long> mp)
    {
 
        // Every number that divides N
        // compared with Mid whether it
        // also divides Mid
        for (Map.Entry<Long, Long> e : mp.entrySet()) {
 
            // cnt stores number of times mid
            // factorial can be divided with
            // e.getKey() (which is number that
            // also divides N e.getValue() times)
            long cnt = 0;
 
            // Iterating till power of 30
            for (long i = 1; i <= 30; i++) {
 
                // Number theory formula
                long temp = (long)Math.floor(
                    mid / Math.pow(e.getKey(), i));
 
                // If temp is zero we can
                // break it out to speed
                // up the program
                if (temp == 0)
                    break;
 
                // Adding temp to count
                cnt += temp;
            }
 
            // If number of times N is divided
            // by e.getKey() greater than mid
            // factorial that means mid factorial
            // is not divisible by N return false
            if (e.getValue() > cnt)
                return false;
        }
 
        // Otherwise return true
        return true;
    }
 
    // Function to find minimum value of K
    // such that K! is multiple of N
    static long findMinK(long N)
    {
 
        // Step 1 : Finding all prime divisors
        // of N and their powers
        // Hash map to store prime divisors
        // with its powers
        Map<Long, Long> mp = new HashMap<Long, Long>();
 
        // Count the number of times 2 divides
        long count = 0;
        while (N % 2 == 0) {
 
            // N divide by 2
            N /= 2;
 
            // Increasing the counter
            count++;
        }
 
        // If 2 divides it
        if (count != 0)
            mp.put((long)2, count);
 
        // Check for all the possible numbers
        // that can divide it
        for (long i = 3; i <= Math.sqrt(N); i += 2) {
 
            // Resetting count to zero
            count = 0;
 
            // Divide it until possible
            while (N % i == 0) {
 
                // Increasing the counter
                count++;
 
                // Divide it by i
                N /= i;
            }
 
            // If count is non zero then
            if (count != 0)
                mp.put(i, count);
        }
 
        // If n at the end is a prime number.
        if (N > 2)
            mp.put(N, (long)1);
 
        // Step 2 : Binary Search on answer K
        // low pointer on 2 and high on
        // maximum value
        long low = 2, high = MAX_VALUE;
 
        // While high is greater than to 1
        while (high - low > 1) {
 
            // mid value
            long mid = (high + low) / 2;
 
            // Checking for mid value
            if (test(mid, mp)) {
                high = mid;
            }
            else {
                low = mid + 1;
            }
        }
 
        // If check function is true for
        // low then return low
        if (test(low, mp))
            return low;
 
        // Else return high
        else
            return high;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Input 1
        int N = 30;
 
        // Function Call
        System.out.println(findMinK(N));
    }
}
// This code is contributed by prasad264


Python




import math
 
# Check function of binary search
def test(mid, mp):
    # Every number that divides N
    # compared with Mid whether it
    # also divides Mid
    for e in mp.items():
        # cnt stores number of times mid
        # factorial can be divided with
        # e.first (which is number that
        # also divides N e.second times)
        cnt = 0
 
        # Iterating till power of 30
        for i in range(1, 31):
            # Number theory formula
            temp = mid // math.pow(e[0], i)
 
            # If temp is zero we can
            # break it out to speed
            # up the program
            if temp == 0:
                break
 
            # Adding temp to count
            cnt += temp
 
        # If number of times N is divided
        # by e.first greater than mid
        # factorial that means mid factorial
        # is not divisible by N return False
        if e[1] > cnt:
            return False
 
    # Otherwise return True
    return True
 
# Function to find minimum value of K
# such that K! is multiple of N
def findMinK(N):
    # Step 1 : Finding all prime divisors
    # of N and their powers
    # Hash map to store prime divisors
    # with its powers
    mp = {}
 
    # Count the number of times 2 divides
    count = 0
    while N % 2 == 0:
        # N divide by 2
        N //= 2
 
        # Increasing the counter
        count += 1
 
    # If 2 divides it
    if count:
        mp[2] = count
 
    # Check for all the possible numbers
    # that can divide it
    for i in range(3, int(math.sqrt(N)) + 1, 2):
        # Resetting count to zero
        count = 0
 
        # Divide it until possible
        while N % i == 0:
            # Increasing the counter
            count += 1
 
            # Divide it by i
            N //= i
 
        # If count is non zero then
        if count:
            mp[i] = count
 
    # If n at the end is a prime number.
    if N > 2:
        mp[N] = 1
 
    # Step 2 : Binary Search on answer K
    # low pointer on 2 and high on
    # maximum value
    low, high = 2, int(1e13)
 
    # While high is greater than to 1
    while high - low > 1:
        # mid value
        mid = (high + low) // 2
 
        # Checking for mid value
        if test(mid, mp):
            high = mid
        else:
            low = mid + 1
 
    # If check function is true for
    # low then return low
    if test(low, mp):
        return low
 
    # Else return high
    else:
        return high
 
# Driver Code
if __name__ == "__main__":
    # Input 1
    N = 30
 
    # Function Call
    print(findMinK(N))
 
## This code is contributed by codearcade


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
 
class GFG
{
    // Check function of binary search
    static bool Test(long mid, Dictionary<int, int> mp)
    {
        // Every number that divides N
        // compared with Mid whether it
        // also divides Mid
        foreach (var e in mp)
        {
            // cnt stores the number of times mid
            // factorial can be divided with
            // e.Key (which is a number that
            // also divides N e.Value times)
            long cnt = 0;
 
            // Iterating till power of 30
            for (int i = 1; i <= 30; i++)
            {
                // Number theory formula
                long temp = mid / (long)Math.Pow(e.Key, i);
 
                // If temp is zero we can
                // break it out to speed
                // up the program
                if (temp == 0)
                    break;
 
                // Adding temp to count
                cnt += temp;
            }
 
            // If the number of times N is divided
            // by e.Key is greater than mid
            // factorial, that means mid factorial
            // is not divisible by N, return false
            if (e.Value > cnt)
                return false;
        }
 
        // Otherwise return true
        return true;
    }
 
    // Function to find the minimum value of K
    // such that K! is a multiple of N
    static long FindMinK(int N)
    {
        // Step 1 : Finding all prime divisors
        // of N and their powers
        // Dictionary to store prime divisors
        // with their powers
        Dictionary<int, int> mp = new Dictionary<int, int>();
 
        // Count the number of times 2 divides
        int count = 0;
        while (N % 2 == 0)
        {
            // N divide by 2
            N /= 2;
 
            // Increasing the counter
            count++;
        }
 
        // If 2 divides it
        if (count > 0)
            mp[2] = count;
 
        // Check for all the possible numbers
        // that can divide it
        for (int i = 3; i <= Math.Sqrt(N); i += 2)
        {
            // Resetting count to zero
            count = 0;
 
            // Divide it until possible
            while (N % i == 0)
            {
                // Increasing the counter
                count++;
 
                // Divide it by i
                N /= i;
            }
 
            // If count is non zero then
            if (count > 0)
                mp[i] = count;
        }
 
        // If N at the end is a prime number.
        if (N > 2)
            mp[N] = 1;
 
        // Step 2 : Binary Search on answer K
        // low pointer on 2 and high on
        // maximum value
        long low = 2, high = 10000000000000L;
 
        // While high is greater than to 1
        while (high - low > 1)
        {
            // mid value
            long mid = (high + low) / 2;
 
            // Checking for mid value
            if (Test(mid, mp))
            {
                high = mid;
            }
            else
            {
                low = mid + 1;
            }
        }
 
        // If the check function is true for
        // low then return low
        if (Test(low, mp))
            return low;
 
        // Else return high
        else
            return high;
    }
 
    // Driver Code
    static void Main(string[] args)
    {
        // Input 1
        int N = 30;
 
        // Function Call
        Console.WriteLine(FindMinK(N));
 
        // Wait for user input to exit
        Console.ReadLine();
    }
}


Javascript




// JavaScript code to implement the approach
 
// Check function of binary search
function test(mid, mp) {
     
  // Every number that divides N
  // compared with Mid whether it
  // also divides Mid
  for (let [key, value] of mp.entries()) {
    // cnt stores number of times mid
    // factorial can be divided with
    // e.first (which is number that
    // also divides N e.second times)
    let cnt = 0;
 
    // Iterating till power of 30
    for (let i = 1; i <= 30; i++) {
      // Number theory formula
      let temp = Math.floor(mid / Math.pow(key, i));
 
      // If temp is zero we can
      // break it out to speed
      // up the program
      if (temp === 0) break;
 
      // Adding temp to count
      cnt += temp;
    }
 
    // If number of times N is divided
    // by e.first greater than mid
    // factorial that means mid factorial
    // is not divisible by N return false
    if (value > cnt) return false;
  }
 
  // Otherwise return true
  return true;
}
 
// Function to find minimum value of K
// such that K! is multiple of N
function findMinK(N) {
     
  // Step 1: Finding all prime divisors
  // of N and their powers
  // Hash map to store prime divisors
  // with its powers
  let mp = new Map();
 
  // Count the number of times 2 divides
  let count = 0;
  while (N % 2 === 0) {
    // N divide by 2
    N /= 2;
 
    // Increasing the counter
    count++;
  }
 
  // If 2 divides it
  if (count) mp.set(2, count);
 
  // Check for all the possible numbers
  // that can divide it
  for (let i = 3; i <= Math.sqrt(N); i += 2) {
       
    // Resetting count to zero
    count = 0;
 
    // Divide it until possible
    while (N % i === 0) {
      // Increasing the counter
      count++;
 
      // Divide it by i
      N /= i;
    }
 
    // If count is non zero then
    if (count) mp.set(i, count);
  }
 
  // If n at the end is a prime number.
  if (N > 2) mp.set(N, 1);
 
  // Step 2: Binary Search on answer K
  // low pointer on 2 and high on
  // maximum value
  let low = 2,
    high = 1e13;
 
  // While high is greater than to 1
  while (high - low > 1) {
    // mid value
    let mid = Math.floor((high + low) / 2);
 
    // Checking for mid value
    if (test(mid, mp)) {
      high = mid;
    } else {
      low = mid + 1;
    }
  }
 
  // If check function is true for
  // low then return low
  if (test(low, mp)) return low;
 
  // Else return high
  else return high;
}
 
// Driver Code
 
// Input 1
let N = 30;
 
// Function Call
console.log(findMinK(N));


Output

5







Time Complexity: O(sqrt(N) * log2(K))
Auxiliary Space: O(1)

Related Articles: 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads