📜  最小数S,使得N是因数S或S!的因子!

📅  最后修改于: 2021-04-29 18:34:07             🧑  作者: Mango

给定数字N。您的任务是找到最小的数字S,以使N是S的因数! (S阶乘)。 N可以很大。
例子:

Input  : 6
Output : 3
The value of 3! is 6
This is the smallest number which can have 6 as a factor.

Input  : 997587429953
Output : 998957
If we calculate out 998957!, 
we shall find that it is divisible by 997587429953.
Factors of 997587429953 are 998957 and 998629.

天真的方法
我们从1迭代到N,在每种情况下都计算阶乘。当我们找到能够将N作为因子的阶乘时,我们将其输出。对于较大的N,将很难实现此方法,因为阶乘会变得非常大。
时间复杂度:O(N ^ 2)
优化的朴素方法
而不是从1迭代到N,我们使用二进制搜索。这仍然是一种不好的方法,因为我们仍在尝试计算N!
时间复杂度O(N log N)
最佳解决方案
我们可以首先计算N的所有素数。然后,我们将问题简化为找到具有N的所有素数的阶乘,至少是它们在N中出现的次数。然后我们对从1到N的元素进行二元搜索我们可以利用勒让德公式来检查数字的阶乘是否具有相同的素数。然后,我们找到最小的此类数字。

C++
// Program to find factorial that N belongs to
#include 
using namespace std;
 
#define ull unsigned long long
 
// Calculate prime factors for a given number
map primeFactors(ull num)
{
    // Container for prime factors
    map ans;
 
    // Iterate from 2 to i^2 finding all factors
    for (ull i = 2; i * i <= num; i++)
    {
        while (num % i == 0)
        {
            num /= i;
            ans[i]++;
        }
    }
 
    // If we still have a remainder
    // it is also a prime factor
    if (num > 1)
        ans[num]++;
    return ans;
}
 
// Calculate occurrence of an element
// in factorial of a number
ull legendre(ull factor, ull num)
{
    ull count = 0, fac2 = factor;
    while (num >= factor)
    {
        count += num / factor;
        factor *= fac2;
    }
    return count;
}
 
bool possible(map &factors, ull num)
{
    // Iterate through prime factors
    for (map::iterator it = factors.begin();
            it != factors.end(); ++it)
    {
        // Check if factorial contains less
        // occurrences of prime factor
        if (legendre(it->first, num) < it->second)
            return false;
    }
    return true;
}
 
// Function to binary search 1 to N
ull search(ull start, ull end, map &factors)
{
    ull mid = (start + end) / 2;
 
    // Prime factors are not in the factorial
    // Increase the lowerbound
    if (!possible(factors, mid))
        return search(mid + 1, end, factors);
 
    // We have reached smallest occurrence
    if (start == mid)
        return mid;
 
    // Smaller factorial satisfying
    // requirements may exist, decrease upperbound
    return search(start, mid, factors);
}
 
// Calculate prime factors and search
ull findFact(ull num)
{
    map factors = primeFactors(num);
    return search(1, num, factors);
}
 
// Driver function
int main()
{
    cout << findFact(6) << "n";
    cout << findFact(997587429953) << "n";
    return 0;
}


Java
// Java Program to find factorial that N belongs to
 
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
 
class Test
{
    // Calculate prime factors for a given number
    static HashMap primeFactors(long num)
    {
         
        // Container for prime factors
        HashMap ans = new HashMap(){
            @Override
            public Integer get(Object key) {
                if(containsKey(key)){
                    return super.get(key);                         
            }
            return 0;
        }
    };
 
      
        // Iterate from 2 to i^2 finding all factors
        for (long i = 2; i * i <= num; i++)
        {
            while (num % i == 0)
            {
                num /= i;
                ans.put(i, ans.get(i)+1);
            }
        }
      
        // If we still have a remainder
        // it is also a prime factor
        if (num > 1)
            ans.put(num, ans.get(num)+1);;
        return ans;
    }
     
    // Calculate occurrence of an element
    // in factorial of a number
    static long legendre(long factor, long num)
    {
        long count = 0, fac2 = factor;
        while (num >= factor)
        {
            count += num / factor;
            factor *= fac2;
        }
        return count;
    }
      
    static boolean possible(HashMap factors, long num)
    {
        Set s = factors.keySet();
         
        // Iterate through prime factors
        Iterator itr = s.iterator();
         
        while (itr.hasNext()) {
            long temp = itr.next();
             // Check if factorial contains less
            // occurrences of prime factor
            if (legendre(temp, num) < factors.get(temp))
                return false;
        }
         
        return true;
    }
      
    // Method to binary search 1 to N
    static long search(long start, long end, HashMap factors)
    {
        long mid = (start + end) / 2;
      
        // Prime factors are not in the factorial
        // Increase the lowerbound
        if (!possible(factors, mid))
            return search(mid + 1, end, factors);
      
        // We have reached smallest occurrence
        if (start == mid)
            return mid;
      
        // Smaller factorial satisfying
        // requirements may exist, decrease upperbound
        return search(start, mid, factors);
    }
      
    // Calculate prime factors and search
    static long findFact(long num)
    {
        HashMap  factors = primeFactors(num);
        return search(1, num, factors);
    }
     
    // Driver method
    public static void main(String args[])
    {
        System.out.println(findFact(6));
        System.out.println(findFact(997587429953L));
    }
}
// This code is contributed by Gaurav Miglani


Python3
# Python Program to find factorial that N belongs to
 
# Calculate prime factors for a given number
def primeFactors(num):
 
    # Container for prime factors
    ans = dict()
    i = 2
     
    # Iterate from 2 to i^2 finding all factors
    while(i * i <= num):  
        while (num % i == 0):
            num //= i;
            if i not in ans:
              ans[i] = 0
            ans[i] += 1
 
    # If we still have a remainder
    # it is also a prime factor
    if (num > 1):
      if num not in ans:
        ans[num] = 0
      ans[num] += 1
    return ans;
 
# Calculate occurrence of an element
# in factorial of a number
def legendre(factor, num):
    count = 0
    fac2 = factor;
    while (num >= factor):   
        count += num // factor;
        factor *= fac2; 
    return count;
   
def possible(factors, num):
 
    # Iterate through prime factors
    for it in factors.keys():
 
        # Check if factorial contains less
        # occurrences of prime factor
        if (legendre(it, num) < factors[it]):
            return False;   
    return True;
 
# Function to binary search 1 to N
def search(start, end, factors):
    mid = (start + end) // 2;
 
    # Prime factors are not in the factorial
    # Increase the lowerbound
    if (not possible(factors, mid)):
        return search(mid + 1, end, factors);
 
    # We have reached smallest occurrence
    if (start == mid):
        return mid;
 
    # Smaller factorial satisfying
    # requirements may exist, decrease upperbound
    return search(start, mid, factors);
 
# Calculate prime factors and search
def findFact(num):
    factors = primeFactors(num);
    return search(1, num, factors);
 
# Driver function
if __name__=='__main__':
 
    print(findFact(6))
    print(findFact(997587429953))
     
# This code is contributed by pratham76.


C#
// C# Program to find factorial that N belongs to
using System;
using System.Collections;
using System.Collections.Generic;
 
class Test
{
 
  // Calculate prime factors for a given number
  static Dictionary primeFactors(long num)
  {
 
    // Container for prime factors
    Dictionary ans = new Dictionary();
 
    // Iterate from 2 to i^2 finding all factors
    for (long i = 2; i * i <= num; i++)
    {
      while (num % i == 0)
      {
        num /= i;
        if(!ans.ContainsKey(i))
        {
          ans[i] = 0;
        }
        ans[i]++;
      }
    }
 
    // If we still have a remainder
    // it is also a prime factor
    if (num > 1)
    {
      if(!ans.ContainsKey(num))
      {
        ans[num] = 0;
      }
      ans[num]++;
    }
    return ans;
  }
 
  // Calculate occurrence of an element
  // in factorial of a number
  static long legendre(long factor, long num)
  {
    long count = 0, fac2 = factor;
    while (num >= factor)
    {
      count += num / factor;
      factor *= fac2;
    }
    return count;
  }
 
  static bool possible(Dictionary factors, long num)
  {
 
    foreach (int itr in factors.Keys)
    {
      // Check if factorial contains less
      // occurrences of prime factor
      if (legendre(itr, num) < factors[itr])
        return false;
    }      
    return true;
  }
 
  // Method to binary search 1 to N
  static long search(long start, long end, Dictionary factors)
  {
    long mid = (start + end) / 2;
 
    // Prime factors are not in the factorial
    // Increase the lowerbound
    if (!possible(factors, mid))
      return search(mid + 1, end, factors);
 
    // We have reached smallest occurrence
    if (start == mid)
      return mid;
 
    // Smaller factorial satisfying
    // requirements may exist, decrease upperbound
    return search(start, mid, factors);
  }
 
  // Calculate prime factors and search
  static long findFact(long num)
  {
    Dictionary  factors = primeFactors(num);
    return search(1, num, factors);
  }
 
  // Driver method
  public static void Main()
  {
    Console.WriteLine(findFact(6));
    Console.WriteLine(findFact(997587429953L));
  }
}
 
// This code is contributed by rutvik_56.


输出:

3
998957