zoukankan      html  css  js  c++  java
  • IOI2021集训队作业 173QE Equal Numbers

    给你(n)个数,每次可以将一个数乘任意正整数。对于(kin[0,n]),求进行(k)次操作得到的数列中不同的数的最小值。

    (nle 3*10^5)


    统计每个数的出现次数。将数分成两类:(A)类,存在另一个数为它的不为(1)的正整数倍;(B)类,不存在另一个数为它的不为(1)的正整数倍。

    一种情况是(B)类数不动,于是每种(A)类数的代价是个数次操作,贡献是(-1)

    另一种情况是(B)类数动了。为了使(B)类数产生贡献,必须要钦定另一个数变成所有数的(LCM)。为了最优取出现次数最小的((A)类或(B)类都行)。


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 300005
    #define M 1000000
    int n;
    int buc[M+5];
    int a[N],b[N];
    int na,nb;
    int f[N];
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i){
    		int x;
    		scanf("%d",&x);
    		buc[x]++;
    	}
    	int cnt=0;
    	for (int i=M;i>=1;--i)
    		if (buc[i]){
    			cnt++;
    			bool bz=0;
    			for (int j=i+i;j<=M && !bz;j+=i)
    				if (buc[j])
    					bz=1;
    			if (bz==0)
    				b[++nb]=buc[i];
    			else
    				a[++na]=buc[i];
    		}
    	sort(a+1,a+na+1);
    	int s=0;
    	f[s]=0;
    	for (int i=1;i<=na;++i){
    		s+=a[i];
    		f[s]=max(f[s],i);
    	}
    	if (na+nb>=2){
    		for (int i=1;i<=nb;++i)
    			a[++na]=b[i];
    		sort(a+1,a+na+1);
    		s=a[1]+a[2];
    		f[s]=max(f[s],1);
    		for (int i=3;i<=na;++i){
    			s+=a[i];
    			f[s]=max(f[s],i-1);
    		}
    		for (int i=1;i<=n;++i)
    			f[i]=max(f[i-1],f[i]);
    	}
    	for (int i=0;i<=n;++i)
    		printf("%d ",cnt-f[i]);	
    	return 0;
    }
    
  • 相关阅读:
    pku 1077 Eight
    poj 1700 过河问题 贪心法
    字典树
    [转] 解读IntelliJ IDEA的优缺点
    【转】STL 容器类内部实现
    Google Chrome太强大了
    【转】从哈希存储到Bloom Filter
    [转]我的多年羽毛球自学心得
    好书推荐
    【转】C++错误中英文对照表
  • 原文地址:https://www.cnblogs.com/jz-597/p/13824325.html
Copyright © 2011-2022 走看看