题目链接:点击查看
题目大意:给出一个 p ,求出最小的 n! 使得 p 可以整除 n!
题目分析:因为 p 高达 1e9 ,可以考虑sqrt(n)的算法,也就是唯一分解定理了,分解之后对于每个质因子,我们可以单独讨论,对于某个质因子 p[ i ] ,记录其在 p 中的出现次数 num[ i ] ,我们现在只需要找到一个最小的 k ,使得 k! 内含有大于等于 num[ i ] 个 质因子p[ i ] 即可,然后用答案维护一下 k 的最大值就是答案了
这样问题就转换为了如何找到这个最小的 k ,这里提供两种思路:
第一种思路就是直接二分,因为显然此处的 k 具有单调性,我们的check函数也只需要找 [ 1 , k ] 内一共含有多少个 p[ i ] 就好了
第二种思路就是直接枚举,因为如果都是基于 2 这个质因子,那么 num 最多也只有 30 ,所以不难看出,所有质因子数量之和一定是小于 30 的,这样我们就可以直接枚举了,对于某个质因子 p[ i ] ,每次都加上 p[ i ] 然后计算答案就好了
代码:这里给出第二种思路实现
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--)
{
int n;
scanf("%d",&n);
int ans=-1;
for(int i=2;i*i<=n;i++)
if(n%i==0)
{
int cnt=0;
while(n%i==0)
{
n/=i;
cnt++;
}
int k=0;
for(int j=i;;j+=i)//枚举最小的 k
{
int num=j;
while(num%i==0)
{
num/=i;
k++;
}
if(k>=cnt)
{
ans=max(ans,j);
break;
}
}
}
printf("%d\n",max(ans,n));
}
return 0;
}