文巾解题 793. 阶乘函数后 K 个零

Posted 刘文巾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文巾解题 793. 阶乘函数后 K 个零相关的知识,希望对你有一定的参考价值。

1 题目描述

2 解题思路

令 zeta(x) 为 x! 末尾零的个数。如果 x! 可以分解为素数的乘积,如(2^a * 5^b * \\cdots )的形式,那么 x! 末尾零的个数为 min(a, b) = b。

zeta(x) 就是 x 除以 5 的次数之和,即 zeta(x) 等于\\lfloor \\frac{x}{5^1} \\rfloor + \\lfloor \\frac{x}{5^2} \\rfloor + \\lfloor \\frac{x}{5^3} \\rfloor + \\lfloor \\frac{x}{5^4} \\rfloor + \\cdots

可以看出,zeta(x) 是一个单调递增函数,因此可以使用二分查找求解。

使用二分查找找出满足 zeta(x) = K 的最大 x 和最小 x

由于一定存在 zeta(5a-1) < zeta(5a) = zeta(5a+1) = zeta(5a+2) = zeta(5a+3) = zeta(5a+4) < zeta(5a+5),即如果存在某个 x 使得 zeta(x) = K,那么一定存在连续 5 个数的阶乘末尾零的个数都为 K;如果不存在这样的 x,那么阶乘末尾零的个数为 K 的数字只有 0 个。

class Solution(object):
    def preimageSizeFZF(self, K):
        def zeta(x):
            if(x==0):
                return 0
            else:
                return x//5 + zeta(x//5) 

        lo, hi = 4*K, 5*K + 1

        while lo < hi:
            mi = (lo + hi) // 2
            zmi = zeta(mi)
            if zmi == K: 
                return 5
            elif zmi < K: 
                lo = mi + 1
            else: 
                hi = mi

        return 0
#最终没有找到这个数

接下来解释一下这边二分查找的时候的左边界和右边界是怎么找的:

zeta(x)=\\lfloor \\frac{x}{5^1} \\rfloor + \\lfloor \\frac{x}{5^2} \\rfloor + \\lfloor \\frac{x}{5^3} \\rfloor + \\lfloor \\frac{x}{5^4} \\rfloor + \\cdots \\le \\frac{x}{5^1} +\\frac{x}{5^2}+\\frac{x}{5^3}+ \\frac{x}{5^4}+ \\cdots

我们可以得到

k=zeta(x) )\\le \\frac{\\frac{1}{5}}{1-\\frac{1}{5}}=\\frac{1}{4}x

即x≥4k

zeta(x)=\\lfloor \\frac{x}{5^1} \\rfloor + \\lfloor \\frac{x}{5^2} \\rfloor + \\lfloor \\frac{x}{5^3} \\rfloor + \\lfloor \\frac{x}{5^4} \\rfloor + \\cdots \\ge \\frac{1}{5}x

即x≤5k

复杂度分析

时间复杂度:O(\\log^2 K),二分查找的复杂度为 O(log K),其中每一步计算 zeta 的复杂度也为 O(logK)。

空间复杂度:O(logK),zeta 递归调用栈的大小。

以上是关于文巾解题 793. 阶乘函数后 K 个零的主要内容,如果未能解决你的问题,请参考以下文章

每日一题793. 阶乘函数后 K 个零

文巾解题 1837. K 进制表示下的各位数字总和

文巾解题 189. 旋转数组

文巾解题 1816. 截断句子

阶乘后的零

缺迪杰斯特拉和SPFA] 文巾解题 787. K 站中转内最便宜的航班