跳转至

793. 阶乘函数后 K 个零

题目描述

 f(x) 是 x! 末尾是 0 的数量。回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 。

  • 例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 ;而 f(11) = 2 ,因为 11!= 39916800 末端有 2 个 0 。

给定 k,找出返回能满足 f(x) = k 的非负整数 x 的数量。

 

示例 1:

输入:k = 0
输出:5
解释:0!, 1!, 2!, 3!, 和 4! 均符合 k = 0 的条件。

示例 2:

输入:k = 5
输出:0
解释:没有匹配到这样的 x!,符合 k = 5 的条件。

示例 3:

输入: k = 3
输出: 5

 

提示:

  • 0 <= k <= 109

解法

方法一:二分查找

定义 \(f(x)\)\(x!\) 末尾零的个数,那么

\[ f(x)= \begin{cases} 0, x=0\\ x/5+f(x/5), x>0 \end{cases} \]

定义 \(g(k)\) 表示 \(x!\) 末尾为零的个数为 \(k\) 的最小的 \(x\) 值,那么题目等价于求解 \(g(k+1)-g(k)\)

由于 \(g(k)\) 是单调递增的,因此可以使用二分查找求解 \(g(k)\)

同时,由于 \(f(x)=x/5+f(x/5) \ge x/5\),因此 \(f(5k)\ge k\)。所以,求解 \(g(k)\) 时,二分的右边界可以取 \(5k\)

时间复杂度 \(O(log^2k)\),其中 \(k\) 为题目给定的整数。二分查找 \(g(k)\) 的时间复杂度为 \(O(logk)\),计算 \(f(x)\) 的时间复杂度为 \(O(logx)\),因此总时间复杂度为 \(O(log^2k)\)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution:
    def preimageSizeFZF(self, k: int) -> int:
        def f(x):
            if x == 0:
                return 0
            return x // 5 + f(x // 5)

        def g(k):
            return bisect_left(range(5 * k), k, key=f)

        return g(k + 1) - g(k)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
    public int preimageSizeFZF(int k) {
        return g(k + 1) - g(k);
    }

    private int g(int k) {
        long left = 0, right = 5 * k;
        while (left < right) {
            long mid = (left + right) >> 1;
            if (f(mid) >= k) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return (int) left;
    }

    private int f(long x) {
        if (x == 0) {
            return 0;
        }
        return (int) (x / 5) + f(x / 5);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
    int preimageSizeFZF(int k) {
        return g(k + 1) - g(k);
    }

    int g(int k) {
        long long left = 0, right = 1ll * 5 * k;
        while (left < right) {
            long long mid = (left + right) >> 1;
            if (f(mid) >= k) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return (int) left;
    }

    int f(long x) {
        int res = 0;
        while (x) {
            x /= 5;
            res += x;
        }
        return res;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func preimageSizeFZF(k int) int {
    f := func(x int) int {
        res := 0
        for x != 0 {
            x /= 5
            res += x
        }
        return res
    }

    g := func(k int) int {
        left, right := 0, k*5
        for left < right {
            mid := (left + right) >> 1
            if f(mid) >= k {
                right = mid
            } else {
                left = mid + 1
            }
        }
        return left
    }

    return g(k+1) - g(k)
}

评论

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy