版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82943511
我好菜啊……好菜啊……好菜啊……
阶乘
(fact)
【问题描述】
有 n个正整数 a[i],设它们乘积为 p,你可以给 p乘上一个正整数 q,使 p*q刚好为正整数m的阶乘,求m的最小值。
【输入】
共两行。
第一行一个正整数n。
第二行n个正整数a[i]。
【输出】
共一行
一个正整数m。
【输入样例】
1
6
【输出样例】
3
样例解释:
当p=6,q=1时,p*q=3!
【数据范围与约定】
对于10%的数据,n<=10
对于30%的数据,n<=1000
对于100%的数据,n<=100000,a[i]<=100000
牢骚
我觉得我可能是把这道题想复杂了吧,反正我推了一个半小时,居然连一分都没拿到手%>_<%,
思路离正解很近了,只是可能因为长时间耗在上面,思维固化了,就没想出来代码该怎么写,以后还是别在一道题上吊死
主要还是不知道怎么分解阶乘的质因数
今天评讲完后总算会了一点点了
先看一个简单的问题:
27!里面有多少个3相乘?
27!=1*2*...*27
包含1个3的数有27/(3^1)=9个
包含2个3的数有27/(3^2)=3个
包含3个3的数有27/(3^3)=1个
总共:9+3+1=13 个
所以27!里面有13个3相乘。
具体代码实现呢大概也就是用一个while循环不停的除,然后累加即可
分析
首先根据标题 fact,我们就能八九不离十,猜出来要分解质因数了
然后可以把p分解质因数,假设 p=∏ai^bi(ai为质数),那么只要 m!包含了每个ai^bi,m!就包含p。
所以就可以二分答案咯,因为m!这个是单增的
代码
#include<bits/stdc++.h>
#define N 100000
#define in read()
using namespace std;
int n;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
bool mark[N+10];
int pri[N+10],num=0;
void init(){//线性筛素数
mark[1]=1;
for(int i=2;i<=N;++i){
if(!mark[i]) pri[++num]=i;
for(int j=1;j<=num&&i*pri[j]<=N;++j){
mark[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
int a,b[N],maxn=-1,c[N];
void fenjie(int x){//对p进行分解
int tmp;
for(int i=1;i<=num&&pri[i]<=x;++i){
tmp=x;
while(tmp%pri[i]==0){
tmp/=pri[i];
b[pri[i]]++;
maxn=max(maxn,pri[i]);
}
}
if(tmp) b[tmp]++;
}
int check(int m){//二分答案的检验
memset(c,0,sizeof(c));
int tmp;
for(int i=1;i<=num&&pri[i]<=m;++i){
tmp=m;
while(tmp){//就是这里啦,阶乘的分解质因数
c[pri[i]]=(c[pri[i]]+tmp/pri[i]);
tmp/=pri[i];
}
}
for(int i=2;i<=maxn;++i)
if(!mark[i]) if(b[i]>c[i]) return 0;
return 1;
}
int main(){
n=in;
init();
while(n--){
a=in;
fenjie(a);
}
int l=1,r=1000000000,ans=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d",ans);
return 0;
}