• codeforces 300E Empire Strikes Back


    题意:给定一个k和k个数字,求最小的数字n使得n!是∑ai!的倍数。

    思路:设cnt[ i ]表示包含素数i出现的数目。把∑ai!的每一个质数的指数求出来,然后二分判断n是否满足条件即可。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<bitset>
    #include<vector>
    #include<string>
    #include<stack>
    #include<set>
    #define ll long long
    #define PI acos(-1.0)
    #define F first
    #define S second
    #define pb push_back
    #define debug(x); printf("***:%d
    ",x);
    #define des(x); printf("des:%s
    ",x+1);
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    using namespace std;
    const int N=1e6+5;
    const int M=1e7+5;
    ll s;
    ll cao;
    int k;
    ll cnt[M];
    int f[M],prime[M],tot,ans;
    void oula()
    {
        //f[1]=1;
        for (int i=2; i<=1e7; i++)
        {
            if (!f[i])
            {
                prime[++tot]=i; f[i]=i;//欧拉筛筛质数
            }
            for (int j=1; j<=tot; j++)
            {
                if (i*prime[j]>1e7) break;
                f[i*prime[j]]=i;
                if (i%prime[j]==0)
                    break;
            }
        }
    }
    bool check(ll x)
    {
        for(int i=1;i<=tot;i++)
        {
            ll temp=x;
            ll sum=0;
            while(temp)
            {
                temp/=prime[i];//求二分的数包含某一个质数的数目。
                sum+=temp;
            }
            if(sum<cnt[prime[i]])
                return false;
        }
        return true;
    }
    int main()
    {
        oula();
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%lld",&cao);
            s+=cao;
            cnt[cao]++;
        }
        for(ll i=1e7;i>=2;i--)
            cnt[i]+=cnt[i+1];//例:如果是质数29,则29!还要加上31!,30!等里包含的29数目。
        for(ll i=1e7;i>=2;i--)
        {
            cnt[i/f[i]]+=cnt[i];//求大数里包含的小质数数目。
            if(i!=f[i])
                cnt[f[i]]+=cnt[i];
        }
        ll l=1,r=s;
        while(l<=r)
        {
            ll mid=l+r>>1;
            if(check(mid))
            {
                r=mid-1;
            }
            else 
                l=mid+1;
        }
        printf("%lld
    ",l);
        return 0;
    }
  • 相关阅读:
    31 把数组排成最小的数 + 仿函数的写法就记忆这个就行了
    30 整数中1出现的次数(从1到n整数中1出现的次数)这题很难要多看*
    29 连续子数组的最大和
    c/c++ struct的大小以及sizeof用法
    28 最小的K个数
    27 数组中出现次数超过一半的数字
    26 字符串的排列
    Python 实例2—购物车
    python_threading模块实现多线程详解(转)
    Ubuntu 16.04 安装Postman
  • 原文地址:https://www.cnblogs.com/switch-waht/p/13679339.html
Copyright © 2020-2023  润新知