http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4433

C++版本一

题解:这个题让我想起了https://codeforces.com/contest/837/problem/D

https://blog.csdn.net/weixin_43272781/article/details/84581632

思路差不多,因为这个题5肯定比2少所以只要考虑5就行

不过我考虑了二分答案和每个数字前面5出现的情况所以感觉还行

就是内存有点多,时间有点长

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG

using namespace std;
typedef long long ll;
const int N=20000000;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m;
int a[N];
int sloved(int x){
    return x/5+x/25+x/125+x/625+x/3125+x/15625+x/78125+x/390625+x/1953125+x/9765625+x/48828125+x/244140625;
}
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
    scanf("%d",&t);
    int T=0;
    while(t--){
        scanf("%d",&n);

        cout << "Case "<<++T<<": ";
        int l=5;
        int r=n*5;
        int mid ,ans=1;

        while(l<=r){
            mid=(l+r)>>1;
            int tmp=sloved(mid);
            if(tmp==n){
                cout << mid-mid%5 << endl;
                ans=0;
                break;
            }else if(tmp<n){
                l=mid+1;
            }else{
                r=mid-1;
            }
        }
        if(ans)
        cout << "impossible" << endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

 

C++版本二

题解:
二分枚举n,若将阶乘中所有的数拆分成质因子的乘积,发现只有2*5 才能产生
0,同时2 会比5 的个数多。故直接二分n,check 5 的个数。

#include <stdio.h>

int five[30];
int total_five;

void init(){
    five[0] = 5;
    total_five = 1;
    for(int i = 1; five[i-1]*5ll<1e9; i ++) {
        five[i] = five[i-1]*5;
        total_five ++;
    }
}

int get_suff_count(int m){
    int ret = 0;
    for(int i = 0; i < total_five; i ++){
        ret += m/five[i];
    }
    return ret;
}

int bin(int l, int r, int Q){
    int ret = -1;
    while( l <= r){
        int m = (l+r) >> 1;
        int suff_count = get_suff_count(m);
        if(suff_count == Q){
            ret = m;
            r = m-1;
        }else if(suff_count < Q){
            l = m+1;
        }else{
            r = m-1;
        }
    }
    return ret;
}

int main(){
//    freopen("data1.in", "r", stdin);
//    freopen("data1.out", "w", stdout);
    int T, Q;
    int ica = 1;
    scanf("%d", &T);
    init();
    while( T --){
        scanf("%d", &Q);
        int ans = bin(5, 5e8, Q);
        if(ans == -1) printf ("Case %d: impossible\n", ica ++);
        else printf("Case %d: %d\n", ica ++, ans);
    }
    return 0;
}

C++版本三

题解:模拟一下牛顿迭代,那么可以使得复杂度变得更低。记get(x)为x!中零的个
数。那么答案必定在x~x-(k-get(x))之中。最后注意一下当(k-get(x))小于10
的时候暴力一下。

///O(玄学)
#include<bits/stdc++.h>
using namespace std;

int get(int x){
    int ret = 0;
    while(x){
        ret += x;
        x /= 5;
    }
    return ret;
}
int solve(int n){
    int x = n;
    while(true){
        int ret = get(x);
        if(abs(ret - n) <= 10){
            for(int i = min(n - ret, 0); i <= max(n - ret, 0); ++i){
                if(get(x + i) == n) return (x + i) * 5;
            }
            return -1;
        }
        x -= ret - n;
    }

}
int main()
{
//    freopen("data1.in", "r", stdin);
//    freopen("check1.out", "w", stdout);
    int t;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; ++cas){
        printf("Case %d: ", cas);
        int k;
        scanf("%d", &k);
        int ans = solve(k);
        if(ans == -1)   puts("impossible");
        else    printf("%d\n", ans);
    }
    return 0;
}