• Trailing Zeroes


    题目:

    Trailing Zeroes 

    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.

    Input

    Input starts with an integer T (≤ 10000), denoting the number of test cases.

    Each case contains an integer Q (1 ≤ Q ≤ 108) in a line.

    Output

    For each case, print the case number and N. If no solution is found then print 'impossible'.

    Sample Input

    3

    1

    2

    5

    Sample Output

    Case 1: 5

    Case 2: 10

    Case 3: impossible

    题解:

    解法一:

    这是一个二分经典题,主要思路为定义一个求n!后面0的数量的函数,然后二分。为什么要二分呢,因为你用朴素算法方法求的话,每次都要循环1e8次,肯定会TL,用二分查找可以快很多。

    (二分搜索,在有序序列查找值上非常方便。通过一次比较,可以把解的范围缩小一半。反复与区间的重点进行比较,就可以不断把解的范围缩小到原来的一半,最终在O(logn)次的比较之内求得最终的解。)

    求n!后面0的数量请参考我的CSDN博客中的一篇文章:https://blog.csdn.net/qq_45328552/article/details/98206579

    我会在代码里分析一下二分。

    #include <iostream>
    
    using namespace std;
    
    typedef long long ll;
    
    int search(ll n)
    {
        int sum = 0;
        
        while(n)
        {
            sum += n/5;
            n /= 5;
        }
        
        return sum;
    }
    
    int main()
    {
    //    freopen("input.txt","r",stdin);    //注释!注释!!! 
        
        int t, n;
        
        cin >> t;
        
        for(int i = 1; i <= t; i ++ )
        {
            cin >> n;
            
            ll head = 0, tail = 5e8 + 5, mid; 
            //定义二分的头和尾及mid,注意定义成long long类型,因为二分一般都是求非常大的数 
            while(head <= tail) //二分循环需要满足的条件,头小于尾 
            {
                mid = (head + tail) / 2;  
                
                if(search(mid) < n) head = mid + 1; //search(mid)小于n,则所求值必在右边,mid以及mid左边的数都不满足,因此让头等于mid+1 
                else if(search(mid) > n) tail = mid - 1; //search(mid)大于n,所求值必在左边,mid及mid右边的数都不满足,因此让尾等于mid-1 
                else break; //等于则跳出循环,因为已经确定了要找的值 
            }
            
            if(head > tail) printf("Case %d: impossible
    ", i); //head > tail找到不满足条件还找不到,说明已经完全二分还找不到符合条件的数,输出false 
            else printf("Case %d: %d
    ", i, mid - mid % 5);    //根据上面的代码可以知道这是search(mid)=n符合条件的值,输出即可 
        }    //输出mid-mid%5的原因是阶乘后面0的数量相同的数会有重复的而这里要求满足条件的最小值6、7、8和5的阶乘后面0的数量是相同的,6、7、8减去6、7、8 % 5后就变成满足条件的最小值了                        
        return 0;
    }

     解法二:

    我同学用了打表的方法做出了这道题,也是很强了。打表的时候看着数据4、5一组很慢、很慢地通过,最后成功AC,真的很爽。

    打表注意事项:1、明白阶乘为0的数量的最小数为5的倍数,从而以5为倍数进行循环。

    2、提前打好表,使用标记数组的思维去打表。不要在循环体内一次一次地去打表,肯定TL;

    #pragma GCC optimize(2)
    #include <bits/stdc++.h> 
    using namespace std;
    
    typedef long long ll;
    const int N=1e8+10;
    
    int f[N];
    
    int search(int n)
    {
        int num = 0;
        while(n)
        {
            num+=n/5;
            n/=5;
        }
        return num;
     } 
    
    int main()
    {
    //    freopen("input.txt", "r", stdin);
        //提交时注释,调试时取消注释!!! 
        int t;
        cin >> t;
        for(int i=5;i<1e8+10;i+=5)
        {
            f[search(i)]=i;
        }
        int tmp;
        for(int i=0;i<t;i++)
        {
            scanf("%d",&tmp);
            if(f[tmp]!=0) printf("%d
    ",f[tmp]);
            else printf("impossible
    ");
        }        
        return 0;
    }

    皓齿蛾眉,命曰伐性之斧。 --《吕氏春秋 》

    http://www.dxswb.com/shijian/219063.html
  • 相关阅读:
    快速复习正则表达式
    常用正则表达式
    用SqlConnectionStringBuilder修改连接超时时间
    GRUB 启动 WIN PE 镜像(ISO)
    win xp 关闭动画屏幕角色,那只小狗
    win xp firefox,chrome 在浏览网页时字体发虚,可以设置为新宋体
    OpenFileDialog 打开快捷方式时,返回的是快捷方式引用的路径,而不是快捷方式(.lnk)自身的路径
    关闭IE 对剪切板访问的提示
    svn 提交代码 自动过滤技巧,自动过滤不想提交的文件和文件夹
    WinForm 打开文件夹
  • 原文地址:https://www.cnblogs.com/pioneer1/p/11290936.html
Copyright © 2020-2023  润新知