链接:

时间限制: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≤10^3^,p≤10^9^
题解:
两个方法:
二分与贪心

在什么条件下n!会是p的倍数呢?
n!的素因子集合包含p的素因子集合,也就是对于每个质因子,阶乘n中的数量大于对应p中的数量

贪心:

暴力做法,从2开始循环质因数,对于每次一个质因数i,看p1当前能分解出多少个,然后再枚举n,看n最小为多少能做到质因数i的数量大于等于p1
代码中有句sum=max(sum,j);什么含义?你想如果我们之前求出n=9包含3的数量满足条件,那枚举5时得到n=10,10的阶乘是包含9的阶乘,也就是10!既满足质因数2也满足3,所以求最大max
代码内也有注释

代码:

#include<bits/stdc++.h>
using namespace std;
int main() {
    int t,p1,sum=0;
    cin>>t;
    while(t--) 
    {
        cin>>p1;
        sum=0;
        for(int i=2;i*i<=p1;++i)
         if(p1%i==0) 
         {
            int cnt=0;
            while(p1%i==0) 
            {
                p1/=i;
                ++cnt;
            }//当前质因子i在p1中的数量 
            int tmp=0;
            int j;
            for(j=i;;j+=i) 
            {
                     int n=j;
                    while(n%i==0)
                    {
                        n/=i;
                        ++tmp;
                    } //记录当前质因数在n中的数量 

                if(tmp>=cnt) break;//找到一个数,使得他的质因数i的数量多于等于p1 
            }
            sum=max(sum,j); 
 //           cout<<sum<<endl;
        }
        cout<<max(sum,p1)<<endl;
    }
}

二分:

其实就是把方法一中暴力的过程改成更为巧妙的二分过程,先将p1的质因数存入数组prime,然后二分查找,寻找最小的n,满足他的质因数i的数量多于等于p1
代码借鉴其大佬博客写的

代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 3;
int prime[maxn], cnt[maxn], len = 0;
//素因子,素因子的个数,数组长度

int judge(int mid) {
    for (int i = 1; i <= len; i++)
    {
        int n = mid
        int sum = 0;
        while (n) 
        {
            sum += n / prime[i];
            n /= prime[i];
        }
        if (sum < cnt[i]) return 0;//不满足条件就找下一个n 
    }
    return 1;//满足要求 
}
int main() {
    int T; 
    cin>>T;
    int l,r,sum; 
    while (T--) 
    {
        int p1;
        cin>>p1;
        len = 0;
        memset(cnt, 0, sizeof cnt);
        for (int i = 2; i * i <= p1; i++)
        if ( p1 % i==0) 
        {
            prime[++len] = i;
            while (p1 % i==0) 
            {
                cnt[len]++;
                p1 /= i;
            }
        }
        if (p1 > 1) 
        {
            prime[++len] = p1;
            cnt[len]++;
        }
        //求出素因子及其个数
        l = 1, r = 1e9, sum = 0;
        while (l <= r) {
            int mid = l + r >> 1;
            if (judge(mid)) 
            {
                r = mid - 1;
                sum = mid;
            }
            else l = mid + 1; 
        }
        //二分查找
        printf("%d\n", sum);
    }
    return 0;
}