首页 > 其他 > 详细

NOIP模拟 阶乘

时间:2018-10-05 17:56:23      阅读:147      评论:0      收藏:0      [点我收藏+]

【题目描述】

有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模拟 阶乘

原文:https://www.cnblogs.com/Ishtar/p/9745127.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!