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; }