题目链接
题目大意
给定一个正整数p,求一个最小的正整数 n,使得 n! 是 p 的倍数
题目思路1
看到此题还是会想到质因数分解,但是没想到是需要p和n!都要质因数分解。可以把p分解的因子和次数用
一个pair储存。然后可以发现其实这个题目是满足二分条件的。
注意n质因数分解时那个变量j要设为long long 。因为可能会爆int,有关i,j在for循环里面是乘法操作的一定要注意很容易wa
代码1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e3;
int t,p,cnt;
pair<int,int> a[maxn];
bool check(int x){
for(int i=1;i<=cnt;i++){
int sum=0;
for(ll j=a[i].first;j<=x;j=j*a[i].first){//唯一分解定理 ,j可能会爆int
sum=sum+x/j;
}
if(sum<a[i].second){//不满足
return false;
}
}
return true;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&p);
int temp=p;
cnt=0;
memset(a,0,sizeof(a));
for(int i=2;i*i<=p;i++){
if(p%i){//不可以整除
continue;
}
a[++cnt].first=i;//first代表因子
while(p%i==0){
a[cnt].second++;//second代表有几个first
p=p/i;
}
}
if(p!=1){//p为质数
a[++cnt].first=p;
a[cnt].second=1;
}
int l=1,r=temp,ans=inf;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){//注意题目要求
ans=min(ans,mid);
r=mid-1;
}else{
l=mid+1;
}
}
printf("%d\n",ans);
}
return 0;
}
题目思路2
其中p1,p2,…,pn为互不相同的质数。那么我们对每个质数pi,找到能凑到指数ki的最小数字,比如pi=2,ki=2,那么2含有1个2因子,
4含有2个2因子,加起来为3>=2,所以凑成2^2至少要4!。我们对每个质数都进行这样的一次寻找,ans保存最大的那个就行了。
则不需要二分
代码2
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int p,t,cnt,j;
map<int,int> a;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&p);
int ans=1;
for(int i=2;i*i<=p;i++){
if(p%i){
continue;
}
int sum=0;
while(p%i==0){//表示有sum个i因子
p=p/i;
sum++;
}
a.clear();//清空
for(j=1,cnt=0;cnt<sum;j++){//这段代码有点神仙,自己演算一下就知道
a[j*i]=a[j]+1;
cnt=cnt+a[j*i];
}
ans=max(ans,i*(j-1));//注意是j-1
}
ans=max(ans,p);//这个不要忘,因为p可能自己也是一个质数
printf("%d\n",ans);
}
return 0;
}