📜  阶乘中至少n位的最小数字

📅  最后修改于: 2021-05-07 04:49:05             🧑  作者: Mango

给定数字n。任务是找到其阶乘至少包含n位数字的最小数字。
例子:

Input : n = 1
Output : 0
0! = 1, hence it has 1 digit.

Input : n = 2
Output : 4
4! = 24 and 3! = 6, hence 4 is 
the smallest number having 2 
digits in its factorial

Input : n = 5
Output : 8

在关于数阶乘中计数数字的文章中,我们讨论了如何有效地找到阶数中的位数。
我们使用下面的公式来查找位数

Kamenetsky’s formula approximates the number
of digits in a factorial by :
f(x) = log10(((n/e)n) * sqrt(2*pi*n))

Thus, we can pretty easily use the property of logarithms to ,
f(x) = n*log10((n/e)) + log10(2*pi*n)/2 

现在我们需要确定可以找到至少n位数字的阶乘的间隔。以下是一些观察结果:

  • 对于一个很大的数字,我们总是可以说它的阶乘比数字本身具有更多的数字。例如,阶乘100的158位数字大于100。
  • 但是,对于较小的数字,情况可能并非如此。例如,阶乘8仅具有5位数字,小于8。实际上,直到21的数字都遵循此趋势。

因此,如果我们从0开始搜索!到n!要查找至少包含n位数字的结果,我们将无法找到较小数字的结果。
例如,假设n = 5,现在当我们在[0,n]中搜索时,我们可以获得的最大位数为3(找到5!= 120)。但是,如果我们搜索[0,2 * n](0到10),则可以找到8!有5位数字。
因此,如果我们可以搜索从0到2 * n的所有阶乘,那么总是会有一个数字k的阶乘中至少有n位数字(建议读者自己尝试找出这个事实)。

We can say conclude if we have to find a number k,
such that k! has at least n digits, we can be sure
that k lies in [0,2*n]

i.e., 0<= k <= 2*n

因此,我们可以在0到2 * n之间进行二进制搜索,以找到具有至少n位数字的最小数字。

C++
// A C++ program to find the smallest number
// having at least n digits in factorial
#include 
using namespace std;
 
// Returns the number of digits present in n!
int findDigitsInFactorial(int n)
{
    // factorial of -ve number doesn't exists
    if (n < 0)
        return 0;
 
    // base case
    if (n <= 1)
        return 1;
 
    // Use Kamenetsky formula to calculate the
    // number of digits
    double x = ((n*log10(n/M_E)+log10(2*M_PI*n)/2.0));
 
    return floor(x)+1;
}
 
// This function receives an integer n and returns
// an integer whose factorial has at least n digits
int findNum(int n)
{
    // (2*n)! always has more digits than n
    int low = 0, hi = 2*n;
 
    // n <= 0
    if (n <= 0)
        return -1;
 
    // case for n = 1
    if (findDigitsInFactorial(low) == n)
        return low;
 
    // now use binary search to find the number
    while (low <= hi)
    {
        int mid = (low+hi) / 2;
 
        // if (mid-1)! has lesser digits than n
        // and mid has n or more then mid is the
        // required number
        if (findDigits(mid) >= n && findDigits(mid-1)


Java
// A Java program to find the
// smallest number having at
// least n digits in factorial
class GFG
{
// Returns the number of
// digits present in n!
static int findDigitsInFactorial(int n)
{
    // factorial of -ve number
    // doesn't exists
    if (n < 0)
        return 0;
 
    // base case
    if (n <= 1)
        return 1;
 
    // Use Kamenetsky formula to
    // calculate the number of digits
    double x = ((n * Math.log10(n / Math.E) +
                     Math.log10(2 * Math.PI * n) / 2.0));
 
    return (int)(Math.floor(x) + 1);
}
 
// This function receives an integer
// n and returns an integer whose
// factorial has at least n digits
static int findNum(int n)
{
    // (2*n)! always has
    // more digits than n
    int low = 0, hi = 2 * n;
 
    // n <= 0
    if (n <= 0)
        return -1;
 
    // case for n = 1
    if (findDigitsInFactorial(low) == n)
        return low;
 
    // now use binary search
    // to find the number
    while (low <= hi)
    {
        int mid = (low + hi) / 2;
 
        // if (mid-1)! has lesser digits
        // than n and mid has n or more
        // then mid is the required number
        if (findDigitsInFactorial(mid) >= n &&
            findDigitsInFactorial(mid - 1) < n)
            return mid;
 
        else if (findDigitsInFactorial(mid) < n)
            low = mid + 1;
 
        else
            hi = mid - 1;
    }
    return low;
}
 
// Driver Code
public static void main(String[] args)
{
    System.out.println(findNum(1));
    System.out.println(findNum(2));
    System.out.println(findNum(5));
    System.out.println(findNum(24));
    System.out.println(findNum(100));
    System.out.println(findNum(1221));
}
}
 
// This Code is Contributed by mits


Python3
# Python3 program to find the
# smallest number
# having at least n digits
# in factorial
 
import math
 
# Returns the number of digits
# present in n!
def findDigitsInFactorial(n):
     
    # factorial of -ve number
    # doesn't exists
    if (n < 0):
        return 0
 
    # base case
    if (n <= 1):
        return 1
 
    # Use Kamenetsky formula to calculate the
    # number of digits
    M_E=2.7182818284590452354
    M_PI=3.14159265358979323846
    x = ((n*math.log10(n/M_E)+math.log10(2*M_PI*n)/2.0))
 
    return int(math.floor(x)+1)
 
# This function receives an
# integer n and returns
# an integer whose factorial has
# at least n digits
def findNum(n):
     
    # (2*n)! always has more
    # digits than n
    low = 0
    hi = 2*n
 
    # n <= 0
    if (n <= 0):
        return -1
 
    # case for n = 1
    if (findDigitsInFactorial(low) == n):
        return int(round(low))
 
    # now use binary search to
    # find the number
    while (low <= hi):
        mid = int((low+hi) / 2)
 
        # if (mid-1)! has lesser digits than n
        # and mid has n or more then mid is the
        # required number
        if ((findDigitsInFactorial(mid) >= n and
            findDigitsInFactorial(mid-1)


C#
// A C# program to find the
// smallest number having at
// least n digits in factorial
using System;
 
class GFG
{
     
// Returns the number of
// digits present in n!
static int findDigitsInFactorial(int n)
{
    // factorial of -ve number
    // doesn't exists
    if (n < 0)
        return 0;
 
    // base case
    if (n <= 1)
        return 1;
 
    // Use Kamenetsky formula to
    // calculate the number of digits
    double x = ((n * Math.Log10(n / Math.E) +
                     Math.Log10(2 * Math.PI * n) / 2.0));
 
    return (int)(Math.Floor(x) + 1);
}
 
// This function receives an integer
// n and returns an integer whose
// factorial has at least n digits
static int findNum(int n)
{
    // (2*n)! always has
    // more digits than n
    int low = 0, hi = 2 * n;
 
    // n <= 0
    if (n <= 0)
        return -1;
 
    // case for n = 1
    if (findDigitsInFactorial(low) == n)
        return low;
 
    // now use binary search
    // to find the number
    while (low <= hi)
    {
        int mid = (low + hi) / 2;
 
        // if (mid-1)! has lesser digits
        // than n and mid has n or more
        // then mid is the required number
        if (findDigitsInFactorial(mid) >= n &&
            findDigitsInFactorial(mid - 1) < n)
            return mid;
 
        else if (findDigitsInFactorial(mid) < n)
            low = mid + 1;
 
        else
            hi = mid - 1;
    }
    return low;
}
 
// Driver Code
static public void Main ()
{
    Console.WriteLine(findNum(1));
    Console.WriteLine(findNum(2));
    Console.WriteLine(findNum(5));
    Console.WriteLine(findNum(24));
    Console.WriteLine(findNum(100));
    Console.WriteLine(findNum(1221));
}
}
 
// This code is contributed by akt_mit


PHP
= $n &&
            findDigitsInFactorial($mid - 1) < $n)
            return (int)round($mid);
 
        else if (findDigitsInFactorial($mid) < $n)
            $low = $mid + 1;
 
        else
            $hi = $mid - 1;
    }
    return (int)round($low);
}
 
// Driver Code
echo findNum(1) . "\n";
echo findNum(2) . "\n";
echo findNum(5) . "\n";
echo findNum(24) . "\n";
echo findNum(100) . "\n";
echo findNum(1221) . "\n";
 
// This code is contributed by mits
?>


Javascript


输出:

0
4
8
24
70
532