1

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

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
ranger_sim_g
  • 160
  • 1
  • 10

2 Answers2

4

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.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • can you give me any hint why `x >= y * 4` ? can't prove it... @Dmitry Bychenko – fardinabir Oct 05 '19 at 08:20
  • 1
    @fardinabir: I've edited the answer, I've added the proof – Dmitry Bychenko Oct 07 '19 at 07:00
  • @DmitryBychenko Shouldn't the inequality be x <= (y+1)*5. Like, y = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + .... Now, thus, y >= [x / 5]. But, we can't directly say y >= x/5. For x<25. Thus, shouldn't the inequality be y >= x/5 - 1. This should cover all the cases. Or, we can change the inequality depending on the number. Like for bigger numbers your inequality holds good, and for smaller the one I suggested. – Vedanta Mohapatra Aug 24 '22 at 05:30
3

Focus on the number of 2s and 5s that makes up a number. e.g. 150 is made up of 2*3*5*5, there 1 pair of 2&5 so there's one trailing zero. Each time you increase the tested number, try figuring out how much 2 and 5s are in the number. From that, adding up previous results you can easily know how much zeros its factorial contains.

For example, 15!=15*...*5*4*3*2*1, starting from 2:

Number   2s  5s  trailing zeros of factorial
2        1   0   0
3        1   0   0
4        2   0   0
5        2   1   1
6        3   1   1
...
10       5   2   2
...
15       7   3   3
..
24      12   6   6
25      12   8   8   <- 25 counts for two 5-s: 25 == 5 * 5 == 5**2
26      13   8   8 
..   

Refer to Peter de Rivaz's and Dmitry Bychenko's comments, they have got some good advices.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Richard Yan
  • 1,276
  • 10
  • 21