牛客算法周周练4 C-阶乘

阶乘

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述
给定一个正整数 p
求一个最小的正整数 n,使得 n! 是 p 的倍数

输入描述:
第一行输入一个正整数T表示测试数据组数
接下来T行,每行一个正整数p

输出描述:
输出T行,对于每组测试数据输出满足条件的最小的n

示例1
输入:

4
1
2
4
8

输出:

1
2
4
4

备注:
T<=1e3,P<=1e9

解题思路:
开始想直接暴力计算阶乘到p的倍数,但是c++会溢出,java会超时.所以显然暴力是不行的。然后记得之前有遇到一个题目,好像是蓝桥杯还是哪的题目,让你求n以内有几个k(差不多就这个意思),比如求100以内5的个数,那就先除以5,因为每五个必定有一个为5的倍数,然后就是25的倍数,每25个必定有5*5的倍数,因为前面算过了5的个数,所以也是加一即可,按照这种算法,能求出n的阶乘包含的素因子个数(因为n的阶乘就相当于1到n的素因子相乘的结果),然后通过二分来找到最接近答案的解即可.

代码如下:

#include

using namespace std;
typedef long long ll;
const int N = 2e4 + 5;

inline bool isPrime(ll a) {//判断素数
    int len = sqrt(a);
    for (int i = 2; i <= len; i++) {
        if (a % i == 0)return false;
    }
    return true;
}

int prime[N], ans, sum[N], mn;

inline bool solve(int a) {//判断当前这个数的阶乘是不是p的倍数
    for (int i = 0; i < ans; i++) {
        int now = a, cnt = 0;
        while (now > 0 && cnt < sum[i]) {//计算p的第i个素因子的个数在a的阶乘下是否够个数
            cnt += now / prime[i];
            now /= prime[i];
        }
        if (cnt < sum[i])return false;//如果a的阶乘没有足够组成p的素因子个数,那就返回false
    }
    mn = a;//只有true才会改变值,这个值会保留二分最后的答案
    return true;//a的阶乘是p的倍数,返回true.
}

int main() {
    ios::sync_with_stdio(false);
    int t;
    while (cin >> t)
        while (t--) {
            int p, q;
            cin >> p;
            q = p;
            if (isPrime(p)) {//如果p是素数,直接输出本身即可,因为只有到本身才能是自己的倍数
                cout << p << endl;
            } else {
                ans = 0;
                mn = -1;
                int len = sqrt(p);
                for (int i = 2; i <= len && p >= i; i++) {//取出p的所有素因子,并记录个数
                    bool f = false;
                    while (p % i == 0) {
                        prime[ans] = i;
                        if (!f)sum[ans] = 1;
                        else sum[ans]++;
                        p /= i;
                        f = true;
                    }
                    if (f)ans++;
                }
                if (p > 1) {//因为取素因子只取到p的根号,出现类似p=2*7这个情况,最后一个数不是1就记录下来
                    prime[ans] = p;
                    sum[ans++] = 1;
                }
                int l = 0, r = q;
                while (l <= r) {//二分找答案
                    int mid = (l + r) >> 1;
                    if (solve(mid))r = mid - 1;
                    else l = mid + 1;
                }
                cout << mn << endl;
            }
        }
    return 0;
}

你可能感兴趣的:(刷题)