Is there a more precise modified stirling's approximation formula for calculating n!?

264 Views Asked by At

I am trying to solve a problem of competitive programming

Consider two integer sequences $f(n) = n!$ and $g(n) = a^n$, where $n$ is a positive integer. For any integer $a > 1$ the second sequence is greater than the first for a finite number of values. But starting from some integer $k$, $f(n)$ is greater than $g(n)$ for all $n \ge k$. You are to find the least positive value of $n$ for which $f(n) > g(n)$, for a given positive integer $a > 1$.

Constraints: 2 <= a <= 10^6 There is no constraint of n given. Full problem statement Problem statement

I tried to solve this using Stirling's approximation formula I took log on both sides and solved it but the online judge is returning wrong answer. I wonder if there is a more precise formula or if you can suggest any new method to reduce above functions?

My code for this if that helps.

     int l = in.readInt();
        int low = 1;
        int high = 1000000;
        int ans = 0;
        double loga = Math.log10(l);
        outer:
        while (low <= high) {

            int middle = (low + high) / 2;
            double sum = 0.0;
            double sum1 = 0.0;
           /*
            int i=1;
            for (i = 1; i <= middle; i++) {
                sum = sum + Math.log10(i);                      //This is giving TLE  //Method 1

            }
            sum1 = sum + Math.log10(i);
            sum = sum / (double) middle;
            sum1 = sum1 / (double) (middle + 1.0);
              */
                    //Method 2
                     sum = ((0.5) * Math.log10(2 * Math.PI * (double) middle) + (double) middle * Math.log10(((double) middle / Math.E))) / (double) middle;
            sum1 = ((0.5) * Math.log10(2 * Math.PI * ((double) middle + 1.0)) + ((double) middle + 1.0) * Math.log10((((double) middle + 1.0) / Math.E))) / ((double) middle + 1.0);
             //This is giving wrong answer.


            if (sum <= loga && sum1 > loga) {
                ans = middle;
                break outer;
            } else if (sum > loga) {
                high = middle - 1;

            } else {
                low = middle + 1;
            }

        }

        out.printLine(ans + 1);
1

There are 1 best solutions below

3
On BEST ANSWER

This is not an answer to your question, just another approach. Using Stirling's approximation is overkill for small numbers.

Note that $n! > a^n$ iff $\prod_{k=1}^n { k \over a} >1$.

(Equivalently, $n! > a^n$ iff $\sum_{k=1}^n \ln{ k \over a} >0$. This avoids some issues with underflow for large $a$.)

def f(a):
    n = 1
    s = 1.0/a
    while True:
        if s>1:
            return n
        n = n+1
        s = (s*n)/a