Search code examples
algorithmpython-2.7factorialtrailing

Finding natural numbers having n Trailing Zeroes in Factorial


I need help with the following problem.

Given an integer m, I need to find the number of positive integers n and the integers, such that the factorial of n ends with exactly m zeroes.

I wrote this code it works fine and i get the right output, but it take way too much time as the numbers increase.

a = input()

while a:
 x = []
 m, n, fact, c, j = input(), 0, 1, 0, 0
 z = 10*m
 t = 10**m

 while z - 1:
  fact = 1
  n = n + 1   

  for i in range(1, n + 1):
     fact = fact * i

  if fact % t == 0 and ((fact / t) % 10) != 0:
     x.append(int(n))
     c = c + 1

  z = z - 1

 for p in range(c):
  print x[p],

 a -= 1
 print c

Could someone suggest me a more efficient way to do this. Presently, it takes 30 seconds for a test case asking for numbers with 250 trailing zeros in its factorial.

Thanks


Solution

  • To get number of trailing zeroes of n! efficiently you can put

    def zeroes(value):
        result = 0;
    
        d = 5;
    
        while (d <= value): 
            result += value // d; # integer division
            d *= 5;
    
        return result; 
    
    ...
    
    # 305: 1234! has exactly 305 trailing zeroes 
    print zeroes(1234) 
    

    In order to solve the problem (what numbers have n trailing zeroes in n!) you can use these facts:

    • number of zeroes is a monotonous function: f(x + a) >= f(x) if a >= 0.
    • if f(x) = y then x <= y * 5 (we count only 5 factors).
    • if f(x) = y then x >= y * 4 (let me leave this for you to prove)

    Then implement binary search (on monotonous function).

    E.g. in case of 250 zeroes we have the initial range to test [4*250..5*250] == [1000..1250]. Binary search narrows the range down into [1005..1009].

    1005, 1006, 1007, 1008, 1009 are all numbers such that they have exactly 250 trainling zeroes in factorial

    Edit I hope I don't spoil the fun if I (after 2 years) prove the last conjecture (see comments below):

    Each 5**n within facrtorial when multiplied by 2**n produces 10**n and thus n zeroes; that's why f(x) is

    f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ...
    

    where [...] stands for floor or integer part (e.g. [3.1415926] == 3). Let's perform easy manipulations:

    f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ... <= # removing [...]
            x / 5  +  x / 25  +  x / 125  + ... +  x / 5**n  + ... =
            x * (1/5 + 1/25 + 1/125 + ... + 1/5**n + ...) =
            x * (1/5 * 1/(1 - 1/5)) =
            x * 1/5 * 5/4 =
            x / 4
    

    So far so good

     f(x) <= x / 4 
    

    Or if y = f(x) then x >= 4 * y Q.E.D.