leetcode 793. Preimage Size of Factorial Zeroes Function

leetcode 793. Preimage Size of Factorial Zeroes Function

题目描述

Let f(x) be the number of zeroes at the end of x!. (Recall that x! = 1 * 2 * 3 * ... * x, and by convention, 0! = 1.)

For example, f(3) = 0 because 3! = 6 has no zeroes at the end, while f(11) = 2 because 11! = 39916800 has 2 zeroes at the end. Given K, find how many non-negative integers x have the property that f(x) = K.

Note:

  • K will be an integer in the range [0, 10^9].

Difficulty: hard
793. Preimage Size of Factorial Zeroes Function


中文描述
题目定义了一个函数 f(x) f ( x ) ,表示 x! x ! 后末尾有几个0。比如 f(3)=0,f(11)=2 f ( 3 ) = 0 , f ( 11 ) = 2 ,因为 3!=6,11!=39916800 3 ! = 6 , 11 ! = 39916800 ,所以 3! 3 ! 后面没有零,所以 f(3)=0 f ( 3 ) = 0 ,而 11! 11 ! 最后有2个零,所以 f(11)=2 f ( 11 ) = 2 。现在给定一个 K K ,问有几个x,能使得 f(x)=K f ( x ) = K


输入格式
输入一个值KK表示结尾有K个零。


Examples:

  1. Input: K = 0
    Output: 5
    解释:
    0!=1, 1!=1, 2!=2, 3!=6, 4!=5 结尾都没有零,所以有5个数满足 f(x)=0 f ( x ) = 0 .

  2. Input: K = 5
    Output: 0
    解释:
    没有 x x 能够满足f(x)=5,所以结果是0


解答思路

记得leetcode上有一题是给定一个 x x ,判断x!末尾有几个零。172. Factorial Trailing Zeroes。这题则是它的变形。

  • 二分查找

    1.通常情况下我们考虑遍历 x x 来寻找答案。而随着x的增大, f(x) f ( x ) 也是一个增加的态势。所以自然而然的我们会考虑到使用二分查找 x x 来优化该问题。

    2.我们首先取定x的最大最小的范围,最小范围很好确定,从0开始即可,而最大范围则需要考虑下。通过观测得到 0!,1!,2!,3!,4! 0 ! , 1 ! , 2 ! , 3 ! , 4 ! 末尾没有零, 5!,6!,7!,8!,9! 5 ! , 6 ! , 7 ! , 8 ! , 9 ! 末尾有1个零, 10!,11!,12!,13!,14! 10 ! , 11 ! , 12 ! , 13 ! , 14 ! 末尾有2个零, 15!,16!,17!,18!,19! 15 ! , 16 ! , 17 ! , 18 ! , 19 ! 末尾有3个零, 20!,21!,22!,23!,24! 20 ! , 21 ! , 22 ! , 23 ! , 24 ! 末尾有4个零,到了 25!,26!,27!,28!,29! 25 ! , 26 ! , 27 ! , 28 ! , 29 ! 末尾有6个零。我们发现每过5个数,末尾的零至少增加1个,并且这样连续的5个数的 f(x) f ( x ) 是一样的(因为能够产生零,一定是因数中包含2*5,或则直接包含10的情况。因数中包含10只有10,20这样的数,而包含5则是只有5,15这样的数,所以每连续5个数的结果都是一样的)。所以对于 K K ,我们x只需取到 5K 5 K 的位置即可。

    3.对 x x 进行二分查找。如果存在x使f(x)=K,则根据第二步的分析,我们知道至少有5个数能满足 f(x)=K f ( x ) = K ,所以返回5。否则就不存在,返回0。

    4.复杂度估计 O(logK) O ( l o g K )


代码

class Solution(object):
    def preimageSizeFZF(self, K):
        """
        :type K: int
        :rtype: int
        35MS
        """
        if K == 0:
            return 5
        # 计算x!的末尾有几个0
        def trailingZeroes(n):
            if n == 0:
                return 0
            import math
            k = int(math.log(n, 5))
            ans = 0
            for i in range(1, k + 1):
                ans += n // 5 ** i
            return ans
        # 选择合适的最大位置,通过观测可以发现K*5必然比x大(f(x) = K)
        hight, low = K * 5, 5
        # 之后就是二分查找,如果有一定为5个连续的,否则就为0
        while low <=hight:
            mid = (low + hight) // 2
            a = trailingZeroes(mid)
            if a > K:
                hight = mid - 1
            elif a < K:
                low = mid + 1
            else:
                return 5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值