版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82947878
【问题描述】
有 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
解析:
直接把一个数分解质因数,把结果存起来。
显然,
中含有的各个质因数个数是单调不减的,所以这道题可以二分答案。
根据木桶原理,我们要令所有的质因数个数都能满足,这是check的依据。
那么怎么统计 中有多少个某种质因数呢?
就像统计位数一样统计就行了。
显然, 中质数 的次数是 ,直接统计即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
re ll num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline
void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs int P=100005;
bitset<P> mark;
int prime[P],pcnt;
inline
void linear_sieves(int len=P-5){
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i;
for(int re j=1;j<=pcnt&&i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
int cnt[P];
int maxp;
inline
int div(int a){
for(int re i=1;i<=pcnt&&a>1;++i){
if(a==a/prime[i]*prime[i])maxp=max(maxp,i);
while(a==a/prime[i]*prime[i])a/=prime[i],++cnt[prime[i]];
}
}
inline
bool check(int x){
for(int re i=1;i<=maxp;++i){
int cont=0;
for(ll k=prime[i];k<=x&&cont<cnt[prime[i]];k*=prime[i])cont+=x/k;
if(cont<cnt[prime[i]])return false;
}
return true;
}
int n;
signed main(){
linear_sieves();
n=getint();
for(int re i=1;i<=n;++i){
int x=getint();
div(x);
}
int l=1,r=100000000;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
outint(l);
return 0;
}