Equal Numbers Gym - 101612E(思维, 模拟,贪心)

题目大意

给出n个数字,分别改变0~n个数字,使得数字种类数最少,每次打印数字种类数。

思路

让种类数变小总共有两种方法,一是n个数中一种数字是另一种的倍数,改变一种数就可以减少一种数,另一种是改变两种数使得都变成这两个数的公倍数。
可以先统计各种数的个数,然后从小到大排一下因为改变个数最少的数越容易减少种类数。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = (int)1e6 + 10, inf = 0x3f3f3f3f;

int cnt[maxn];
int ct1[maxn], ct2[maxn];
int cur1, cur2;
int n;

void init() {
    memset(cnt, 0, sizeof(cnt));
    cur1 = cur2 = 0;
}

int main() {
//    freopen("input.txt", "r", stdin);
    freopen("equal.in", "r", stdin);
    freopen("equal.out", "w", stdout);
    init();
    cin >> n;
    for(int i = 0, t; i < n; i++) {
        scanf("%d", &t);
        cnt[t]++;
    }
    for(int i = 0; i < maxn; i++) {
        if(cnt[i]) {
            ct1[cur1++] = cnt[i];
            for(int j = 2*i; j < maxn; j+=i) {
                if(cnt[j]) {
                    ct2[cur2++] = cnt[i];
                    break;
                }
            }
        }
    }
    sort(ct1, ct1+cur1);
    sort(ct2, ct2+cur2);
    cout << cur1;
    for(int p=0,q=0,sp=0,sq=0,i=1; i <= n; i++) {
        while(p<cur1&&sp+ct1[p]<=i) {
            sp+=ct1[p++];
        }
        while(q<cur2&&sq+ct2[q]<=i) {
            sq+=ct2[q++];
        }
        cout << " " << cur1 - max(p-1, q);
    }
    cout << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值