Reverse factorial

前端 未结 17 1409
南笙
南笙 2020-12-05 03:12

Well, we all know that if N is given it\'s easy to calculate N!. But what about the inverse?

N! is given and you are about to find N - Is that possible ? I\'m curio

相关标签:
17条回答
  • 2020-12-05 03:43

    Here is some clojure code:

    (defn- reverse-fact-help [n div]
        (cond (not (= 0 (rem n div))) nil
              (= 1 (quot n div)) div
              :else (reverse-fact-help (/ n div) (+ div 1))))
    (defn reverse-fact [n] (reverse-fact-help n 2))
    

    Suppose n=120, div=2. 120/2=60, 60/3=20, 20/4=5, 5/5=1, return 5

    Suppose n=12, div=2. 12/2=6, 6/3=2, 2/4=.5, return 'nil'

    0 讨论(0)
  • 2020-12-05 03:44

    If the input number is really N!, its fairly simple to calculate N.

    A naive approach computing factorials will be too slow, due to the overhead of big integer arithmetic. Instead we can notice that, when N ≥ 7, each factorial can be uniquely identified by its length (i.e. number of digits).

    • The length of an integer x can be computed as log10(x) + 1.
    • Product rule of logarithms: log(a*b) = log(a) + log(b)

    By using above two facts, we can say that length of N! is:

    which can be computed by simply adding log10(i) until we get length of our input number, since log(1*2*3*...*n) = log(1) + log(2) + log(3) + ... + log(n).

    This C++ code should do the trick:

    double result = 0;
    for (int i = 1; i <= 1000000; ++i) {  // This should work for 1000000! (where inputNumber has 10^7 digits)
        result += log10(i);
        if ( (int)result + 1 == inputNumber.size() ) {    // assuming inputNumber is a string of N!
            std::cout << i << endl;
            break;
        }
    }
    

    (remember to check for cases where n<7 (basic factorial calculation should be fine here))

    Complete code: https://pastebin.com/9EVP7uJM

    0 讨论(0)
  • 2020-12-05 03:45

    Yes. Let's call your input x. For small values of x, you can just try all values of n and see if n! = x. For larger x, you can binary-search over n to find the right n (if one exists). Note hat we have n! ≈ e^(n ln n - n) (this is Stirling's approximation), so you know approximately where to look.

    The problem of course, is that very few numbers are factorials; so your question makes sense for only a small set of inputs. If your input is small (e.g. fits in a 32-bit or 64-bit integer) a lookup table would be the best solution.

    (You could of course consider the more general problem of inverting the Gamma function. Again, binary search would probably be the best way, rather than something analytic. I'd be glad to be shown wrong here.)

    Edit: Actually, in the case where you don't know for sure that x is a factorial number, you may not gain all that much (or anything) with binary search using Stirling's approximation or the Gamma function, over simple solutions. The inverse factorial grows slower than logarithmic (this is because the factorial is superexponential), and you have to do arbitrary-precision arithmetic to find factorials and multiply those numbers anyway.

    For instance, see Draco Ater's answer for an idea that (when extended to arbitrary-precision arithmetic) will work for all x. Even simpler, and probably even faster because multiplication is faster than division, is Dav's answer which is the most natural algorithm... this problem is another triumph of simplicity, it appears. :-)

    0 讨论(0)
  • 2020-12-05 03:46

    Simply divide by positive numbers, i.e: 5!=120 ->> 120/2 = 60 || 60/3 = 20 || 20/4 = 5 || 5/5 = 1

    So the last number before result = 1 is your number.

    In code you could do the following:

    number = res
    for x=2;res==x;x++{
        res = res/x
    
    } 
    

    or something like that. This calculation needs improvement for non-exact numbers.

    0 讨论(0)
  • 2020-12-05 03:47

    C/C++ code for what the factorial (r is the resulting factorial):

    int wtf(int r) {
        int f = 1;
    
        while (r > 1)
            r /= ++f;
    
        return f;
    }
    

    Sample tests:

    Call: wtf(1)
    Output: 1
    
    Call: wtf(120)
    Output: 5
    
    Call: wtf(3628800)
    Output: 10
    
    0 讨论(0)
  • 2020-12-05 03:48
    int inverse_factorial(int factorial){
        int current = 1;
        while (factorial > current) {
            if (factorial % current) {
                return -1; //not divisible
            }
            factorial /= current;
            ++current;
        }
        if (current == factorial) {
            return current;
        }
        return -1;
    }
    
    0 讨论(0)
提交回复
热议问题