SGU[154] Factorial

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了好几次,后来发现是二分的上界设置的太小了。

原文地址:https://www.cnblogs.com/Ivy-End/p/4320181.html