NOIP模擬 階乘(質因數分解+二分答案)
阿新 • • 發佈:2018-12-13
【題目描述】
有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; }