NOIP模拟 阶乘
【题目描述】
有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值。
【输入格式】
共两行。
第一行一个正整数n。
第二行n个正整数a[i]。
【输出格式】
共一行
一个正整数m。
【样例输入】
1
6
【样例输出】
3
【备注】
对于10%的数据,n<=10
对于30%的数据,n<=1000
对于100%的数据,n<=100000,a[i]<=100000
【题目分析】
这是第几次被二分答案上界给neng死了。。。10分滚粗。。。
首先可以先将p分解质因数,可以推出最后m!一定是包含了p的所有质因子的。
所以就可以二分m的值(上界要设很大,否则如果出现100000个相同数(或类似这种情况),最后m值就会很大),判断一下是否包含p,如果可以就下调,否则上调。
【代码~】
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL maxn=100010; LL P[maxn],s1[maxn],s2[maxn]; LL tot,n,a,last; bitset<maxn> isprime; void pre() { isprime[0]=isprime[1]=1; for(LL i=2;i<=100000;++i) { if(!isprime[i]) { for(LL j=i+i;j<=maxn;j+=i) isprime[j]=1; P[++tot]=i; } } } LL check(LL x) { memset(s2,0,sizeof(s2)); for(LL i=1;P[i]<=x&&i<=tot;++i) { LL tmp=x; while(tmp) { tmp/=P[i]; s2[i]+=tmp; } } for(LL i=1;i<=last;++i) if(s1[i]>s2[i]) return false; return true; } void fj(LL x) { if(x==1||x==0) return; for(LL i=1;P[i]<=x&&i<=tot;++i) { while(x%P[i]==0) { x/=P[i]; s1[i]++; } last=max(last,i); } } int main() { pre(); scanf("%lld",&n); for(LL i=1;i<=n;++i) { scanf("%lld",&a); fj(a); } LL l=1,r=100000000000; while(l<r) { LL mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%lld",l); return 0; }