Editorial for Ổ cắm
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
\(\color{red}{\text{Spoiler Alert}_{{}_{{}^{{}^{v2.0}}}}}\)
\(\color{red}{\text{Khuyến khích bạn đọc trước khi đọc phần lời giải xin hãy thử code ra thuật của mình dù nó có sai hay đúng}}\)
\(\color{red}{\text{Sau đó từ phần bài giải và thuật toán trước đó mà đối chiếu, rút nhận xét với thuật của mình và thu được bài học (không lãng phí thời gian đâu).}}\)
\(\color{orange}{\text{Hint 1 <Brute-force>}}\)
- Thử từng dãy và kiểm tra trong những cái hợp lệ lấy cái nhỏ nhất
\(\color{orange}{\text{Hint 2 <Greedy> <Sorting>}}\)
- Ưu tiên lấy những cái lớn hơn chúng ta sẽ lấy ít cái nhất
\(\color{orange}{\text{Hint 3 <Distrubition Counting>}}\)
- Vì giới hạn \(a_i\) (\(1 \leq a_i \leq 50\)) nhỏ hơn nhiều với \(n\)
Chúng ta có thể lưu các giá trị theo tần số xuất hiện và duyệt từ giá trị lớn tới bé
\(\color{goldenrod}{\text{Approach}}\)
-
Đầu tiên chúng ta có miễn phí một ô ở đầu nên ta sẽ giảm \(m\) đi 1
-
Với những ổ cắm sau, mỗi ổ cắm tốn 1 ô để cắm sang ổ khác, nên ổ có \(x\) ô cắm sẽ có \(x - 1\) ô cho các thiết bị
Ổ cắm \(1\) là vô nghĩa nên ta cũng chẳng cần xét
\(\color{green}{\text{Preference AC Code }}\): Greedy, Distrubition Counting
\(^{^{\color{purple}{\text{Complexity : }} O(n)\ \color{purple}{\text{time}}\ ||\ O(1)\ \color{purple}{\text{memory}}}}\)
C++
int main()
{
int n, k;
cin >> n >> k;
k--; /// free
/// distrubition counting
vector<int> a(51, 0);
while (n--) a[readInt()]++;
int res = 0;
for (int x = 50; x >= 2; --x)
{
while (a[x] > 0)
{
int t = min((k + (x - 1) - 1) / (x - 1), a[x]);
k -= (x - 1) * t;
a[x] -= t;
res += t;
if (k <= 0)
{
cout << res;
return 0;
}
}
}
cout << -1;
return 0;
}
Comments