Problem H: 阶乘的零

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;
}

猜你喜欢

转载自blog.csdn.net/qq_42079027/article/details/81215238
今日推荐