问题描述
满足N!的末尾恰好有K个0的最小的N是多少?
如果这样的N不存在输出一1。
思路解析
末尾的0是由10产生的,而10是由质数2和5产生的
在求阶乘的过程中,只要是偶数就会有2,而5相对2更少,所以对于10的数量我们可以用计算5的数量来代替
所以我们的目标就是求1-N中有多少个5
1-5,1-10,1-15,1-20,1-25,分别有1,2,3,4,5+1个5
不难看出,5的个数是最后一个数除以5的商(直至不够除5,因为有些数包括多个5,例如25,包含了两个5)
def five_count(num):
count = 0
while !(num%==5) :
#商即为5的个数,可以看作是1*5,2*5,3*5... 1,2,3就是包括前面数字中的5的个数的总和
count += num//5
num = num//5
return count
因为要求的N要求最小,即N一定是5的倍数
但是范围太大,即使我们只找5的倍数,还是会超时,
既然是查找,我们便可以利用二分法
l = 1
r = 10**19
while(l<r):
mid = (l+r)//2
ct = five_count(mid)
#一直循环到最接近的结果或符合条件的最终结果
if ct < k:
l = mid + 1
else:
r = mid
由于二分循环条件是l<r,(l<=r可能会造成死循环)
所以在最后还要考虑l=r的情况
#当r==l时
if k == five_count(l):
print(l)
但是二分法查找的不仅仅是5的倍数,因此我们要考虑非5的倍数
对于非5倍数,我们考虑最接近该数的小于他的5的倍数,换一个说法,即考虑该数除5的商,不考虑余数
我们只需要把循环条件改成num//5即可
def five_count(num):
count = 0
#不是5的倍数也可以
while (num//5):
#商即为5的个数,可以看作是1*5,2*5,3*5... 1,2,3就是包括前面数字中的5的个数的总和
count += num//5
num = num//5
return count
完整代码
import os
import sys
# 请在此输入您的代码
#计算从1~num中有多少个5,不是5的倍数也可以
def five_count(num):
count = 0
#不是5的倍数也可以
while (num//5):
#商即为5的个数,可以看作是1*5,2*5,3*5... 1,2,3就是包括前面数字中的5的个数的总和
count += num//5
num = num//5
return count
k = int(input())
l = 1
r = 10**19
while(l<r):
#mid = l + ((r - l) >> 1)
mid = (l+r)//2
ct = five_count(mid)
#一直循环到最接近的结果或符合条件的最终结果
if ct < k:
l = mid + 1
else:
r = mid
#l、r、mid三者最后均相等
#当r==l时
if k == five_count(l):
print(l)
else:
print(-1)