• JZOJ 5791 阶乘 —— 因数


    题目:https://jzoj.net/senior/#main/show/5791

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

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

    首先,p * q = m!,也就是 p 是 m! 的一个因数;

    把 p 质因数分解,那么 m! 的每个对应质因数的次数都 >= p 中对应质因数的次数;

    不必乘出来 p,只要把每个 a[i] 质因数分解即可;

    对于 m!,统计质因数的次数就是 cnt[i] += m / pri[i] , m /= pri[i],证明之类的很好想啦。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const maxn=1e5+5,inf=1e9;
    int n,a[maxn],p[maxn],ans,mx,pri[maxn],cnt;
    bool ck(int x)
    {
        if(x<mx)return 0;
        for(int i=2,t,tmp;i<=x&&i<=mx;i++)
        {
            if(!p[i])continue;
            t=0; tmp=x;
            while(tmp)t+=tmp/i,tmp/=i;
            if(t<p[i]){/*printf("t=%d p[%d]=%d
    ",t,i,p[i]);*/ return 0;}
    //        printf("x=%d t=%d p[%d]=%d
    ",x,t,i,p[i]);
        }
        return 1;
    }
    int main()
    {
        freopen("factorial.in","r",stdin);
        freopen("factorial.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            for(int j=2;j*j<=a[i];j++)
                while(a[i]%j==0)p[j]++,a[i]/=j,mx=max(mx,j);
            if(a[i]>1)p[a[i]]++; mx=max(mx,a[i]);
        }
        int l=0,r=inf;
        while(l<=r)
        {
            int mid=((l+r)>>1);
    //        printf("l=%d r=%d mid=%d ck=%d
    ",l,r,mid,ck(mid));
            if(ck(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    第37天新版动画系统和有限状态机
    第36天旧版动画系统
    第35天2D游戏相关
    第34天协同程序和异步加载
    第33天力、射线检测、球形检测和延迟函数
    第32天Line渲染器,物理系统和力
    第31天Camera组件和灯光组件
    第29天动态加载、对象池
    第28天3D数学
    第27天3D数学
  • 原文地址:https://www.cnblogs.com/Zinn/p/9463841.html
Copyright © 2020-2023  润新知