题目链接:leetcode793
题面
题目大意
f ( x ) f(x) f(x) 函数是一个求 x ! x! x! 结果尾部 0 个数的函数,现在给你一个 K ,让你求能够找到多少个 x 使得 f ( x ) = K f(x)=K f(x)=K 。
解题思路
首先,我们考虑这个 f ( x ) f(x) f(x) 函数,不难得出 x ! x! x! 尾部 0 的个数等于该数 2 和 5 因子的组数。分别考虑 x ! x! x! 的 2 因子和 5 因子的个数取最小值即两个因子的组数,显然,对于 n ! n! n! , 5 的因子个数一定小于 2 的因子,所以考虑 5 的因子数。
f
(
x
)
=
⌊
x
5
⌋
+
⌊
x
5
2
⌋
+
.
.
.
f(x)=\lfloor \frac{x}{5} \rfloor + \lfloor \frac{x}{5^2} \rfloor + ...
f(x)=⌊5x⌋+⌊52x⌋+...
显然,
f
(
x
)
f(x)
f(x) 是一个单调递增函数。
转自:推导:传送门
求n!
0的来源 2 * 5 所以一对2和5即可产生一个0,所以0的个数即为min(阶乘中5的个数和2的个数)
又因为是2的倍数的数一定比是5的倍数的数多 所以2的个数一定>=5的个数 所以只需要统计 5 的个数了
例如 5! = 1 * 2 * 3 * 4 * 5
2 2 2 5 一个2和一个5配对出现0 所以5!末尾只有一个零
而在 n = 25 时 可以产生5的有 5 10 15 20 25
即 n/5 = 5个 然鹅 25 = 55 所以少算了一个5
n>=25时,故而需要补上它 因此所有可以产生25的也要加上
即为 n/5 + n/25 然鹅 125 = 525 所以又少算了一个5
n>=125时,故而需要补上它 因此所有可以产生125的也要加上
即为 n/5 + n/25 + n/125 然鹅 625 = 5*125 所以又少算了一个5
继续补上…
所以最终为 n/5 + n/25 + n/125 + n/625 + …
即 n/5 + n/5/5 + n/5/5/5 + n/5/5/5/5 + …
我们考虑二分答案即可。当然,本题找到的符合题意的 x 要么有 5 个,要么没有。证明:当找到一个 x 使得: 5 ∣ x ! 且 f ( x ) = K 5|x!\ 且\ f(x)=K 5∣x! 且 f(x)=K 时,则存在 f ( x + 1 ) = f ( x + 2 ) = f ( x + 3 ) = f ( x + 4 ) = K f(x+1)=f(x+2)=f(x+3)=f(x+4)=K f(x+1)=f(x+2)=f(x+3)=f(x+4)=K 。其实就相当于能够除以 5 后商相同的一定有 5 个。
代码实现
class Solution {
public:
int preimageSizeFZF(int K) {
if (K == 0) return 5;
long long l = 0, r = 5LL * K + 1, mid, s;
while (l < r) {
mid = l + (r - l >> 1);
s = getPrimeSize(mid, 5);
if (s == K) return 5;
if (s > K) r = mid;
else l = mid + 1;
}
return 0;
}
//计算 n! 中 p 的因子个数
int getPrimeSize(long long n, long long p) {
long long sz = 0;
while (n >= p) {
sz += n/p;
n /= p;
}
return sz;
}
};
拓展
计算 n ! n! n! 的 p p p 因子的个数根据上述推导的过程同样成立。