求阶乘 | 第十三届蓝桥杯省赛JavaB组

满足 N!N! 的末尾恰好有 KK 个 00 的最小的 NN 是多少?

如果这样的 NN 不存在输出 −1−1。

输入格式

一个整数 KK。

输出格式

一个整数代表答案。

数据范围

对于 30%30% 的数据,1≤K≤1061≤K≤106。
对于 100%100% 的数据,1≤K≤10181≤K≤1018。

输入样例:
2
输出样例:
10
题解:

        在阶乘中,只有5能在结尾产生0,而且5必然会在结尾产生0,因为阶乘中除了0!和1!,其他的结果都为偶数。

        所以,一个数的阶乘有几个零,就可以如下:

        10!:10,5 - 4个0

        20!:20,15,10,5 - 4个0

        30!:30,25=5x5,20,15,10,5 - 7个0

        ...

        于是求一个数阶乘末尾有几个0公式:

ans=N/5+N/25+N/125+...+N/5^{i}

         但是考虑到题目给的数据过大,于是采用标准二分,最后答案要乘5,因为我么二分求的数是N/5而不是N。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;
const int INF=1e16;

ll n;

ll get(ll t){
    ll ans=0;
    while(t!=0){
        ans+=t;
        t/=5;
    }
    return ans;
}

void solve(){
    cin >> n;
    ll l=0,r=n;
    ll ans=-1;
    while(l<=r){
        ll m=(l+r)>>1;
        ll num=get(m);
        if(num==n){
            ans=m;
            break;
        }
        else if(num<n){
            l=m+1;
        }
        else if(num>n){
            r=m-1;
        }
    }
    //cout << ans << "\n";
    if(ans==-1){
        cout << -1;
    }
    else {
        cout << ans*5;
    }
}

int main(){
    solve();
}