阶乘 / factorial

【问题描述】

有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值。

【输入】

共两行。

第一行一个正整数n。

第二行n个正整数a[i]。

【输出】

共一行

一个正整数m。

 

【输入输出样例1】

1

6

3

 

对于10%的数据,n<=10

对于30%的数据,n<=1000

对于100%的数据,n<=100000,a[i]<=100000


 才学会线性筛……

补充——2018-10-14

解释一下代码中的 count函数:【阶乘分解】

N!中的质因子p的个数就等于1~N中每个数包含质因数p的个数之和,那么至少包含一个质因子p的显然有 N/p 个.

同理,p的倍数,即至少包含两个质因子 p 的有 N/p2 个。不过其中一个已经在N/p中算过了,所以只需要统计第 2 个质因子,即累加上 N/p2.

综上,N!中质因子 p 的个数为:

  N/p + N/p2 +N/p3 …… + N/plogpN

code

#include<stdio.h>
#include<algorithm>
#define ll long long 
using namespace std;
const int MX=100001;
bool bz[MX];
int n,tot;
int fr[MX],pri[MX],cnt[MX],a[MX][2];

void pre() {
    for(int i=2;i<=MX;++i) {
        if(!bz[i]) pri[++pri[0]]=i,fr[i]=i;
        for(int j=1;j<=pri[0];++j) {
            if(i*pri[j]>MX) break;
            bz[i*pri[j]]=1;
            fr[i*pri[j]]=pri[j];
            if(i%pri[j]==0) break;
        }
    }
}

int count(int x,int y)
{
    int re=0;
    while(x>=y) {
        re+=x/y;
        x/=y;
    }
    return re;
}

bool jud(int x){
    for(int i=1;i<=tot;++i) {
        if( count(x,a[i][0]) < a[i][1] ) return 0;
    }
    return 1;
}

void pread() {
    int x;
    scanf("%d",&x);
    while(x!=1) {
        cnt[fr[x]]++;
        x/=fr[x];
    }
}



int main()
{
//    freopen("factorial.in","r",stdin),freopen("factorial.out","w",stdout);
    pre();
    scanf("%d",&n);
    while(n--) pread();
    for(int i=2;i<=MX;++i) if(cnt[i]) {
        a[++tot][0]=i;
        a[tot][1]=cnt[i];
    }
    if(tot==0) {
        printf("1");
        return 0;
    }
    int ans,l=1,r=1e10,mid;
    while(l<=r) {
        mid=(l+r)>>1;
        if(jud(mid)) {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-10-14 17:25  qseer  阅读(245)  评论(0编辑  收藏  举报