题解:P13013 [GESP202506 五级] 奖品兑换
非常不错的一道二分答案题目,整体不算太难。
思路如下:我们需要确定最多能兑换多少份奖品。兑换一份奖品可以使用两种方式:一种是使用
给出
-
a\times x + b \times y \le n -
b\times x + a \times y \le m
使用二分法来寻找最大的
-
(a - b)\times x \le n - b\times t -
(a - b) \times x \ge a \times t - m
根据
- 当
a 和b 相等时,只需验证a\times t \le n 且a\times t ≤ m 。 - 当
a > b 时,计算x 的下界和上界,并检查是否存在整数x 在[0, t] 范围内。 - 当
a < b 时,同样计算x 的下界和上界,并检查是否存在整数x 在[0, t] 范围内。
剩下就是二分答案的模板了,相信大家都可以看懂,上代码:
#include <bits/stdc++.h>
using namespace std;
long long n, m, a, b;
bool check(long long t){
if((a + b) * t > n + m)
return false;
if(a == b){
if( a * t <= n && a * t <= m)
return true;
else
return false;
}
double low, high;
if(a > b){
low = (1.0 * a * t - m) / (a - b);
high = (1.0 * n - b * t) / (a - b);
}
else{
low = (1.0 * n - b * t) /(a - b);
high = (1.0 * a * t - m) /(a - b);
}
long long L = ceil(low);
long long R = floor(high);
L = max(L, (long long)0);
R = min(R, t);
return(L <= R);
}
int main(){
cin >> n >> m;
cin >> a >> b;
long long ans = 0;
long long left = 0;
long long right = max(n,m)/min(a,b) + 1;
while(left <= right){
long long mid =(left + right) / 2;
if(check(mid)){
ans = mid;
left = mid + 1;
}
else{
right = mid - 1;
}
}
cout << ans;
return 0;
}