题目链接
求阶乘
个人想法
之前做过计算阶乘结果后面有几个0
的题目,这里看到本题之后,很快就有思路了。想要得到阶乘结果有几个0,首先尾数后面的0,最小肯定是因为因子中存在10。然后,10如何得来呢? 2 * 5 = 10。
在计算阶乘的过程中,以 1~5
为例,有三个因子2(2、4),一个因子5,所以在阶乘过程中,2的个数肯定是远大于5的。
如此,我们这题主要就是计算参与阶乘的所有数中有几个5。
对于给定的 k
,我们可以通过从 5
开始挨个累加,但是如果遇上非常大的数,耗时可能会比较长。所以我们此处使用二分查找,查找可能满足题目输入K的答案。
但是为什么会出现不满足的情况呢?此处使用我列举的一堆草稿…
比如我要找到一个阶乘结果后缀有5个0的时候,是无法找到对应的数的。因为正常情况每遇到一个5的倍数,就会增加一个因子5,但是像25这种数,就包含2个因子5,当乘以25时,后缀一下子多了2个0。
参考代码
Java
import java.util.Scanner;
public class Main {
static long k;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
k = sc.nextLong();
long l = 1L, r = (long) 1e19;
while (l <= r) {
long mid = (r - l) / 2 + l;
if (check(mid) >= k) {
r = mid - 1;
} else {
l = mid + 1;
}
}
if (check(l) == k) System.out.println(l);
else System.out.println(-1);
}
static long check(long n) {
long cnt = 0;
while (n > 0) {
cnt += n / 5;
n /= 5;
}
return cnt;
}
}
C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll k;
ll check(ll n)
{
ll cnt = 0;
while (n)
{
cnt += n / 5;
n /= 5;
}
return cnt;
}
int main()
{
cin >> k;
ll l = 1, r = 5L * k;
while (l <= r)
{
ll mid = l + (r - l) / 2;
if (check(mid) >= k)
r = mid - 1;
else
l = mid + 1;
}
if(check(l) == k) cout << l;
else cout << -1;
return 0;
}