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.
Forget the order of jumps for a second. For each type, only the number of times you use it matters: after uses, it causes exactly rollbacks.
For fixed usage counts , the frog can reach every integer in one continuous interval. The minimum is after choosing all jump lengths , and the maximum is after choosing all jump lengths as large as possible.
So to check if is reachable, you only need to know whether the maximum possible position is at least . Since the interval starts at , every positive point up to that maximum is reachable.
With zero rollbacks, type can be used at most times, giving free distance . Add this over all types first.
One extra rollback assigned to type lets you take exactly more max-length jumps but pays , so it increases the maximum position by . After the free distance, always spend rollbacks on the largest positive value of this expression.
Let us strip the story down to the part that actually matters.
Suppose jump type is used times. Then the number of rollbacks caused by this type is
The order of jumps does not change that count. It also does not change the total rollback distance paid by this type. So for reachability, the frog's exact schedule is mostly noise.
For fixed values , the final position has the form
Each chosen jump distance is any integer from to . Therefore, all possible sums of jump distances form one continuous integer interval from to . No gaps, no weird parity garbage.
So with these fixed counts, the frog can reach every integer from
to
Since , the left endpoint is never a blocker. If the maximum reachable position is at least , then itself is reachable by choosing smaller jump lengths. Nice. The problem becomes: with as few rollbacks as possible, maximize the right endpoint.
Now look at one jump type independently.
With rollbacks, type can be used at most times. That gives free maximum distance
Let
If , the answer is immediately .
What happens after that? Every additional rollback for type lets us use another block of jumps. Those jumps add at most , and the rollback subtracts . So one rollback spent on type changes the maximum position by
That is the whole game. If is negative, spending rollbacks there is trash. If it is zero, it does not help. If it is positive, it gives that much extra reach per rollback.
To minimize the rollback count, we should always use the type with maximum positive :
If and , then the frog can never get farther than the free distance, so the answer is .
Otherwise, we need the smallest integer such that
So
That is it. The frog meditated for years and the solution is a two-variable greedy. Brutal.
Why this is optimal: every plan starts with some number of free jumps and some number of rollback-causing blocks. The free part can contribute at most . Each rollback belongs to some type and can increase the maximum possible position by at most . Therefore, any plan with rollbacks reaches at most . If our formula says fewer than rollbacks are not enough, then no clever ordering can save it. And using the type that attains repeatedly achieves that bound, so the answer is exact.
Edge cases:
Complexity per test case is , with extra memory.
#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 x;
cin >> n >> x;
ll freeReach = 0;
ll bestGain = LLONG_MIN;
for (int i = 0; i < n; i++) {
ll a, b, c;
cin >> a >> b >> c;
freeReach += (b - 1) * a;
bestGain = max(bestGain, b * a - c);
}
if (freeReach >= x) {
cout << 0 << '\n';
} else if (bestGain <= 0) {
cout << -1 << '\n';
} else {
ll need = x - freeReach;
cout << (need + bestGain - 1) / bestGain << '\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 x;
cin >> n >> x;
ll freeReach = 0;
ll bestGain = LLONG_MIN;
for (int i = 0; i < n; i++) {
ll a, b, c;
cin >> a >> b >> c;
freeReach += (b - 1) * a;
bestGain = max(bestGain, b * a - c);
}
if (freeReach >= x) {
cout << 0 << '\n';
} else if (bestGain <= 0) {
cout << -1 << '\n';
} else {
ll need = x - freeReach;
cout << (need + bestGain - 1) / bestGain << '\n';
}
}
}