1. 程式人生 > >NOIP模擬 階乘

NOIP模擬 階乘

是否 spa == memset true 輸出格式 。。 als 格式

【題目描述】

有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; }

NOIP模擬 階乘