Description
描述
You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 1*2*...*N. For example, 5! = 120, 120 contains one zero on the trail.
你的任务是找一个最小的自然数N,使得十进制下N!末尾包含Q个零。正如你知道的N! = 1 * 2 * ... * N。例如,5! = 120,120的末尾包含1个0。
Input
输入
One number Q written in the input (0<=Q<=10^8).
输入包含一个数Q (0 <= Q <= 10^8)。
Output
输出
Write "No solution", if there is no such number N, and N otherwise.
如果不存在这样的N,输出“No solution”,否则输出N。
Sample Input
样例输入
2
Sample Output
样例输出
10
Analysis
分析
统计N!末尾0的个数,其实只要看因数2和5个数的最小值,因为只有2 * 5会产生0。然而实际上因数2的个数远大于因数5的个数,所以只要看因数5的个数。
由于题目给出的空间限制只有4096KB,所以不能打表,会MLE。百度题解以后发现可以用二分。
二分的时候统计1到N这N个数中因数5的个数,我们采用这样的方法:ans = N / 5 + N / 5^2 + N / 5^3 + ...
处理这个过程有两种方法,一个是打表,把5的幂次打表出来,还有一种利用类似秦九邵算法的思想,每次ans += N / 5,同时N /= 5。
需要注意的是,当输入0的时候,要输出1,因为0不是自然数。还有二分的上下界应为[1, 2147483647]。
Solution
解决方案
#include <iostream> using namespace std; const int MAX = 2147483647; int main() { int N; while(cin >> N) { if(N == 0) { cout << 1 << endl; continue; } int l = 1, r = MAX, ans = -1; while(l <= r) { int nMid = (l + r) >> 1; int nTmp = nMid, nCnt = 0; while(nTmp) { nCnt += nTmp / 5; nTmp /= 5; } if(nCnt == N) { ans = nMid; r = nMid - 1; } else if(nCnt < N) { l = nMid + 1; } else { r = nMid - 1; } } if(ans == -1) { cout << "No solution" << endl; } else { cout << ans << endl; } } return 0; }
这道题目一开始WA了好几次,后来发现是二分的上界设置的太小了。