Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
For a fixed discount coefficient , the problem is just multiset matching: old tags are the multiset of , new required tags are the multiset of . Reused tags = intersection size of those two multisets.
So for fixed , the income is
The hard part is computing this fast for every useful , not inventing some weird greedy. There is no greedy here; the tags only care about equal numbers.
The value exactly when
so all original prices inside become . With prefix sums over frequencies, you can get in for each .
For one , iterate over the possible new price . There are only about such values. Compute both the count of items mapped to and their contribution to the new total price.
Now sum over all : checking costs
where . That is the whole trick. Also include , because that represents all larger too: every price becomes .
Let the original prices form a multiset. If we choose some integer , every item with old price gets new price
After that, we need price tags for the multiset of new prices. We already own price tags for the multiset of old prices. Since tags are just numbers, the maximum number of reused tags is exactly the multiset intersection size:
No matching drama, no greedy ceremony. If we need five tags saying 7 and already have two tags saying 7, we reuse two. That's it.
So for a fixed , the income is
We need maximize this over all integer .
Useful range for
Let . If , then every price becomes , because implies .
So every gives the same result. It is enough to test
The value covers all huge discounts.
Computing one fast
For a fixed , which original prices become a new price ?
means
So all prices in the integer interval
turn into .
If we store frequencies of original prices and build a prefix count array
then the number of items that become is
That gives us each bucket in .
For this same bucket:
Then after all buckets are processed:
and we update the answer with
Why this is fast enough
For one fixed , the number of possible new prices is about , because buckets have size .
So the total work over all tested is
With , this is easily fine. The answer can be negative because printing tags can cost an absurd amount, so use long long unless you enjoy self-inflicted pain.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
ll y;
cin >> n >> y;
vector<int> c(n);
int mx = 0;
for (int &v : c) {
cin >> v;
mx = max(mx, v);
}
vector<int> cnt(mx + 2, 0), pref(mx + 2, 0);
for (int v : c) cnt[v]++;
for (int i = 1; i <= mx; i++) pref[i] = pref[i - 1] + cnt[i];
ll ans = LLONG_MIN;
for (int x = 2; x <= mx + 1; x++) {
ll sumNew = 0;
ll reused = 0;
for (int v = 1, l = 1; l <= mx; v++, l += x) {
int r = min(mx, l + x - 1);
int newCnt = pref[r] - pref[l - 1];
if (newCnt == 0) continue;
sumNew += 1LL * v * newCnt;
if (v <= mx) reused += min(cnt[v], newCnt);
}
ll income = sumNew - y * (n - reused);
ans = max(ans, income);
}
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
ll y;
cin >> n >> y;
vector<int> c(n);
int mx = 0;
for (int &v : c) {
cin >> v;
mx = max(mx, v);
}
vector<int> cnt(mx + 2, 0), pref(mx + 2, 0);
for (int v : c) cnt[v]++;
for (int i = 1; i <= mx; i++) pref[i] = pref[i - 1] + cnt[i];
ll ans = LLONG_MIN;
for (int x = 2; x <= mx + 1; x++) {
ll sumNew = 0;
ll reused = 0;
for (int v = 1, l = 1; l <= mx; v++, l += x) {
int r = min(mx, l + x - 1);
int newCnt = pref[r] - pref[l - 1];
if (newCnt == 0) continue;
sumNew += 1LL * v * newCnt;
if (v <= mx) reused += min(cnt[v], newCnt);
}
ll income = sumNew - y * (n - reused);
ans = max(ans, income);
}
cout << ans << '\n';
}
}