1. 程式人生 > >Equal Numbers Gym

Equal Numbers Gym

題目大意

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