题目大意
给出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;
}