2020ICPC·小米 网络选拔赛第一场 A.Intelligent Warehouse (DP)

  • 题意:给你一组数,选一些数出来组成一个排列,使得每个数都能被前一个数整除,求排列的最大元素.

  • 题解:我们先用欧拉筛筛出1e7内所有的质数,设dp[i]表示当前选的数都是i的约数且合法的最大元素的个数.所以我们可以用dp[i]去更新i的倍数的dp值,我们可以靠枚举i的素数倍来降低复杂度,因为合数总是可以由若干个素数的乘积得来.

  • 代码:

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int MMAX=1e7+5;
    int mp[MMAX];
    int prime[MMAX],dp[MMAX];
    bool vis[MMAX]={false};
    int n,pnum=0,x,ans=0;
    void init() ///欧拉筛筛出1e7以内的素数
    {
        for(int i=2;i<=1e7;i++)
        {
            if(!vis[i]) prime[pnum++]=i;
            for(int j=0;j<pnum&&i*prime[j]<=1e7;j++){
                vis[i*prime[j]]=true;
                if(i%prime[j]==0) break;
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            mp[x]++;   ///初始化每个值的个数
        }
        init();
        for(int i=1;i<=1e7;i++){
            dp[i]+=mp[i];  ///让dp[i]加上i本身存在的数
            for(int j=0;j<pnum&&i*prime[j]<=1e7;j++){ ///通过素数枚举dp[i]的倍数
                dp[i*prime[j]]=max(dp[i*prime[j]],dp[i]); ///更新dp[i]的倍数 
            }
            ans=max(ans,dp[i]); ///ans取大
        }
        printf("%d\n",ans);
        return 0;
    }

     

     转载于:https://www.cnblogs.com/lr599909928/p/13881191.html

posted @ 2020-10-27 20:53  小垃圾的日常  阅读(127)  评论(0)    收藏  举报