Trailing Zeroes (III) LightOJ - 1138【n!中末尾0的个数】

题意:

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.
数据范围:\(T ≤ 10^4,1 ≤ Q ≤ 10^8\)

分析:

关键在于给定一个数 \(n\),如何求出 \(n!\)有多少个 \(5\)
一开始想维护一个前缀和,来纪录 \(n!\) 的因子中有多少个 \(5\)。但是时间和空间的花费太多了。
这里介绍一个定理:
\(f(x)\) 表示 \(x!\) 中因子 \(5\) 的个数;

\[f(n!)=\begin{cases} 0 & n<5\\ k+f(k!) & k=\frac{n}{5} \end{cases}\]

推广到任意数 \(x\),有

\[f(n!)=\begin{cases} 0 & n<x\\ k+f(k!) & k=\frac{n}{x} \end{cases}\]

求阶乘,数肯定是连续的。那么先除 \(x\),就把 \([1,n]\) 中含有至少一个因子 \(x\) 的数的个数求出,再使 \(n/x\)。然后依次类推。
知道这个之后,我们直接二分就可以求出答案。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=4e8+100;
int solve(int n)
{
    int res=0;
    while(n)
    {
        res+=n/5;
        n/=5;
    }
    return res;
}
int main()
{
    int t,q,cot=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&q);
        int l=4,r=N;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(solve(mid)>=q)
                r=mid-1;
            else
                l=mid+1;
        }
        printf("Case %d: ",++cot);
        if(solve(l)==q)
            printf("%d\n",l);
        else
            printf("impossible\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12470051.html
今日推荐