Description
定义f(n)为n!的末尾零的个数,例如f(4)=0,f(5)=1。你的任务是对于一个给定的的值x找出最小的n满足f(n)=x。
Input
多组测试数据,每组测试数据包含一个正整数x(1<=x<=10^8)。
Output
对于每组测试数据输出对应的n,若没有n满足则输出“No solution”。
Sample Input
2
Sample Output
10
题意:
给出0的个数,求是几的阶乘,且这个数是满足条件的最小值。
分析:
这个题是反着来的,那我们可以先正着求出一个数的阶乘有几个0,然后遍历一遍,0的个数相等,那么求出答案。
但是直接遍历从5到10^8会超时,所以用二分查找。
怎样找一个数的阶乘有几个0? 里面有几个5就有几个0.比如6=6*5*4*3*2*1有1个⑤就有1个0.
特别注意:125=5*5*5有3个5。25有两个5,25这个数就可以贡献2个0.
所以比如200,总共有[200/5]+[200/5/5]+[200/5/5/5].,为什么这么说呢,200/5是5的倍数有多少个,但是25中有两个5所以我们要加上25的倍数的。
注意:
要找满足条件的最小值。一定是5的倍数。
#include <stdio.h>
long long f(long long n) //找出n末尾0的个数
{
long long num=0;
long long b=1;
while(n>=5) //除以5+除以25+除以125.。。。
{
n=n/5;
num+=n;
}
return num;
}
int main()
{
long long key,i;
int flag;
while(scanf("%lld",&key)==1)
{
flag=0;
long long left=5; //二分查找 效率是logn ,从5开始找
long long right=10000000000;
while(left<right)
{
long long mid=(left+right)/2;
long long q=f(mid);//中间位置
if(key==q) //如果找到,但是。。。最小
{
while(mid%5!=0) //最小的数一定是5的倍数。
mid--;
printf("%lld\n",mid);
flag=1;
break;
}
if(key<q)
right=mid-1;
else
left=mid+1;
}
if(flag==0)
printf("No solution\n"); //没找到
}
return 0;
}
附:二分查找
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[100];
int n,i,key;
cin>>n>>key;//key关键字
for(i = 1; i <= n; i++)cin>>a[i];
sort(a+1,a+n+1);
for(i = 1; i <= n; i++)cout<<a[i]<<" ";
cout<<endl;
int low = 1;
int high = n;
int mid;
while(low <= high)
{
mid = (high + low) / 2;
if(a[mid] == key)break;
if(a[mid] > key)high = mid - 1;
else
low = mid + 1;
}
cout<<"位置:"<<mid<<endl;
return 0;
}