文巾解题 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 递归调用栈的大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值