问题描述:
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
的数量。
- 示例一:
- 输入:
k = 0
。 - 输出:
5
。 - 解释:
0!
, 1!
, 2!
, 3!
和 4!
均符合 k = 0
的条件。
核心思路:
- 该题核心在于数学推导,一开始看到题没有思路,看了几个题解(包括 leetcode 172 阶乘后的零的题解),总算是理解了该题是如何运用二分法找到答案的。
- 首先要理解 leetcode 172 阶乘后的零,如题目所示,172 题要求的是
x
的阶乘 x!
末尾有多少个零。
- 由分析可得,末尾有多少个零相当于阶乘中有多少个质因子
5
。【该部分的分析可看 172 题的官方题解】
- 而质因子
5
的个数在阶乘过程中是不断递增的,x
的阶乘中末尾 0
的数量为 f(x)
,则必定有 f(x) <= f(y), x <= y
。
- 末尾
0
的个数为 0
,则 x
可取 0
、1
、2
、3
和 4
;末尾 0
的个数为 1
,则 x
可取 5
、6
、7
、8
和 9
。 - 那么假设
help(k)
代表的是满足 x
的阶乘末尾 0
的数量等于或小于 k
的 x
的数目,则 help(1) = 10, help(0) = 5
,因此能满足 f(x) = 0
的非负整数 x
的数量为 help(1) - help(0) = 5
。
- 因此能满足
f(x) = k
的非负整数 x
的数量为 help(k+1) - help(k)
。 - 关键在于如何求
help(k)
。
- 如果理解了题意,应该比较容易考虑到二分搜索,二分搜索找到最后一个满足
f(x) <= k
的位置,就相当于是求出了 help(k)
。 - 而二分的边界为
[0, 5*k]
,之所以是 5*k
,可以很直观的看出来 5*k
比 k
多一个质因子 5
。
- 到此需要注意的点应该都已介绍完毕,数学推导的相关题目一直是我弱项,更严谨的解释可以看官方题解,我这里只是简单写一写思路脉络。
代码实现:
class Solution
{
private:
using ll = long long;
ll help(int k)
{
ll l = 0;
ll r = 5LL * k;
while(l <= r)
{
ll mid = l + (r - l) / 2;
if(zeta(mid) < k)
l = mid + 1;
else r = mid - 1;
}
return l+1;
}
int zeta(ll n)
{
int ans = 0;
while(n > 0)
{
n /= 5;
ans += n;
}
return ans;
}
public:
int preimageSizeFZF(int k)
{
if(k <= 1) return 5;
return help(k+1) - help(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
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
参考内容: