开年第一篇博客
我记得以前面试官问了我一个问题即:n!的末尾有几个0,当时语塞,没想起来,现在Mark一下:
Description:
对于数学阶乘N!是个很大的数,我们很难去计算,但是我们很容易计算出N!的末尾0的个数.
Input:
输入第一行包括一个整数T表示接下来的测试实例的个数,接下来的T行,每一行包括一个整数N,1<=N<=100000000
Output:
对于每一个数N,输出这个数对应末尾为0的个数
Sample Input:
3
4
60
1000
Sample Output:
0 14 249
问题分析
要求得末尾为0的个数,就要先分析一下末尾的0是怎么产生的,末尾的0肯定是由2和5产生的,一对2,5相乘产生10,这样末尾就有一个0了。按照常识,一个数中5的个数肯定是要少于2的个数,那么我们只需要求5的个数就好了。这么整个问题就变为在N!中求5的个数就行了。
如果我上面说的不够严谨,引用别人的一个解释加以理解,如下:
- N!=K*10^n, 其中K是不能被10整除的数,那么我们可以根据n就可以得到0的个数,那要如何思考呢
- 对N!进行质因数分解,即:N!=(2^x)(3^y)(5^z)…………,由于2*5=10 ,所以n只与x,z的取值相关
- 于是0的个数=min(x,z),我们可以判断x的个数必然大于n的个数,因为被2整除的数的频率大于被5整除的数的频率,所以n=z
- 你不信3的话,我给你举个例子:在100以内,能被2整除的数有:100,98,96,94,92,90 ,….,10,8,6,4,2.0。一共有51个。而能被5整除的数有:100,95,90,85,80,…,10,5,0。一共20个,嗯嗯,就是这样子的。
解法一
我们要判断的是N!中5的个数,因为N!=N*(N-1)(N-2)(N-3)……2*1
所以我们只要判断5的个数就好了,就是对N,N-1,N-2,….,10,…,2,1中的每一项进行判断,就可以的到5的个数。
代码块
以下是用Python语言实现的上述逻辑的代码:
lines=[]
count=int(input()) # 输入N的个数
for i in range(count):
lines.append(int(input()))
def ZerosCount(N):
"""
Count the Numner of zero in the end of the N!
"""
num=0
for k in range(1,N+1):
j=k
while(j%5==0):
num+=1
j=j/5
return num
print(list(map(ZerosCount,lines)))
输出的结果为:
4
10
600
1000
10000
[2, 148, 249, 2499]
解法二
利用公式z=N/5+N/25+N/5^3+….直到N/5^k为0就好了
代码块
以下使用Python实现上述算法逻辑的代码:
lines=[]
count=int(input())
for i in range(count):
lines.append(int(input()))
def ZerosCount(N):
"""
Count the Numner of zero in the end of the N!
"""
number=0
while N:
number+=N//5
N=N//5
return number
print(list(map(ZerosCount,lines)))
#输出结果如下:
4
10
600
1000
10000
[2, 148, 249, 2499]
Process finished with exit code 0
- 但是把代码写出来是很简单,但是其中的数学原理是什么呢,让我们一起来看一下
- 举例1000里面5的倍数有:5,10,15,20,25,30,35,40,…,990,995,1000
则1000里面5的个数为1000//2=200 Number=200,此时5的次数暂且为200个 - 但是在这200个数中,有些是25的倍数,因为25=5*5,所以25要算两个5,所以5的次数要多加一次。
1000里面25的倍数有:25,50,75,100,125,…,950,975,1000
则1000里面25的个数为1000/25=40,所以5的次数多加40个 - 那么接下来又因为125可以分解为5*5*5 ,即3个5,
1000里面125的倍数有125,250,375,500,625,750,875,900。则1000里面125的个数为1000//125=8,所以5的个数多加8个 - 那么接下来又因为625可以分解为5*5*5*5,即4个5
1000里面625的个数为1,1000//625=1 所以5的个数多加1个
所以5的实际个数为200+40+8+1=249(个)
即,z=N/5+N/5^2+N/5^3+…,在代码里面的可以写简洁一点,归纳如下:
number=0
while N:
number=numbert+N//5
N=N//5 # 在上一个的基础上再除以5,就不用写5^n这种形式啦
return number
#最后再看一组测试输出,感觉非常有意思
10 # 测试的个数
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
[2, 24, 249, 2499, 24999, 249998, 249998, 2499999, 24999999, 249999998]
Process finished with exit code 0