表达式的结果中末尾连续的0出现的个数
题目描述
输入一个自然数n,求表达式 f(n) = 1!×2!×3!×…×n! 的结果末尾有几个连续的0?
输入描述:
自然数n
输出描述:
f(n)末尾连续的0的个数
思路:
这是一道找规律的题目。表达式的结果中末尾出现的0,只与两个数有关,那就是2和5。但事实上,我们通常不考虑2,所以只与一个元素有关,那就是5。为什么不考虑2呢,因为只要阶乘元素中出现了5的倍数,那么必定可以找到相应的偶数因子与这个5配对。因此可以不客气的说,一个5就对应一个末尾的0。
这里我们先考虑对于单个元素 n 的阶乘结果末尾0的个数:
比如,11的阶乘,阶乘的元素中有5,10这两个关键性的数。至于元素5,可以随意和任意偶数配对,使得结果末尾有一个0,至于10,我们仅把他当做“5”看待,那么这个“5”也定能找到相应的偶数(偶数不必是阶乘中的元素,元素中的因子也可以)结合。那么末尾中又有一个0。因此11的阶乘结果,末尾有两个0。
但是如果我们简单地只考虑 n 中包含多少个5,那么是得不到正确答案的。因为有特殊的元素,这个元素仅看作一个“5”是不对的。比如:25,125,625…。25可以看做两个“5”,125可以看做3个“5”,以此类推。那么新的问题来了,怎么计算“5”的总个数?首先我们找出 n 对 5 的取整a1,再找 n 对 25 的取整 a2,再找 n 对 125 的取整 a3…然后将所有的a(i)累加即可。注意是所有a(i)的累加,而不是 a 1 + 2 ∗ a 2 + 3 ∗ a 3....... a1+2*a2+3*a3....... a1+2∗a2+3∗a3....... 因为a1中计算5的取整时,也将25考虑在内了,因此计算25的取整时,尽管一个25的倍数可以看做两个“5”,由于之前已经计数过一次,所以只需要对当前计数一次就行。对于125以及625往后的取整,同理。
单个数的末尾0的计数已经搞清楚了,那么此题目的表达式是前 n 个元素阶乘的累乘。那就好办,遍历每个元素,对每个元素计数其中“5”的个数。累加之后就是答案。可是新的问题来了,计数时,125,625哪个是上限?这与 n 有关,如果 n 本身还没有 25 大,那么只需要与 5 取整就可以。如果 n 是 101,那么 n 与 5 和 25 取整就可以,不需要对 125 取整。所以 n 决定了取整的上限,那么怎么得到这个上限呢?对数函数log就可以!
k
=
i
n
t
(
m
a
t
h
.
l
o
g
(
n
,
5
)
)
k = int(math.log(n,5))
k=int(math.log(n,5))
k 就是最大幂次。好了,代码如下:(python3)
python2 只需要改动 input() 为 raw_input() 即可。
import math
n = int(input())
if n <=0:
print(0)
else:
res = 0
k = int(math.log(n,5))
for i in range(1,n+1):
for j in range(1,k+1):
res += i//(5**j)
print(res)
这样的循环遍历,有点呆,因为对大部分数而言,最大上限的取整就是0。所以我们要换个思路,仍然要遍历每个元素,但我们计数“5”的个数时,稍稍变通。
class CountZero:
def count(self, x):
res, pre = 0, 0
for i in range(5, x+1):
while i%5 == 0:
i //= 5
pre += 1
res += pre
return res
k = int(input())
print(CountZero().count(k))
这里的pre变相的保存了相邻的前面元素的 “5” 的计数,这样不但省去了上面规律的讨论,而且这种接力计数很省时!