UPC5112/NEERC2017 E Equal Numbers(思维)

题目链接: Equal Numbers

题意:给你n个数,你可以每次选一个数并把这个数乘以任意一个整数k。问j次操作后有最少多少种不同的数。(显然0<=j<n)

思考:对于一个数a[i],如果数列中有它的倍数m,显然把a[i]变成m是最优的,否则就把a[i]变成所有数的公倍数。

复习了map的用法。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
map<int,int>mp;
map<int,int>::iterator it;
vector<int>v1,v2;
int f[maxn];
int main()
{
    int n,t,ma=0;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&t);
        ma=max(ma,t);
        mp[t]++;
    }
    it=mp.begin();
    for(;it!=mp.end();++it)
    {
        int x=it->first;
        v1.push_back(it->second);
        for(int j=x+x;j<=ma;j+=x)
        {
            if(mp.count(j))
            {
                v2.push_back(it->second);
                break;
            }
        }
    }
    sort(v2.begin(),v2.end());
    sort(v1.begin(),v1.end());
    int d=0;
    int sum=mp.size();
    memset(f,0x3f,sizeof(f));
    f[0]=mp.size();
    for(int i=0;i<(int)v2.size();++i)
    {
        d+=v2[i];
        f[d]=min(f[d],sum-i-1);
    }
    d=0;
    for(int i=0;i<(int)v1.size();++i)
    {
        d+=v1[i];
        f[d]=min(f[d],sum-i);
    }
    printf("%d",f[0]);
    for(int i=1;i<=n;++i)
    {
        f[i]=min(f[i],f[i-1]);
        printf(" %d",f[i]);
    }
    printf("\n");
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/gzhynl/p/8970803.html