leetcode 793. Preimage Size of Factorial Zeroes Function

13 篇文章 0 订阅
4 篇文章 0 订阅

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、付费专栏及课程。

余额充值