专栏文章
题解:P13013 [GESP202506 五级] 奖品兑换
P13013题解参与者 7已保存评论 7
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 7 条
- 当前快照
- 1 份
- 快照标识符
- @mip0f49t
- 此快照首次捕获于
- 2025/12/03 04:07 3 个月前
- 此快照最后确认于
- 2025/12/03 04:07 3 个月前
题目传送门
故事
先吐槽一句,在考试的时候,编译器给我卡爆了,花了半小时才做完了,当时满分了。
然后我信心满满的提交了题解,第二天题解通道给我关了,我愣住了,然后下午发现原来数据加强了,还升黄了,给我打回来了,我只能重构新算法。
题意
小 A 有 张课堂优秀券, 张作业优秀券。
小 A 可以花 张课堂优秀券和 张作业优秀券或者 张课堂优秀券和 张作业优秀券来换取一个奖品。
我们需要求出最多可以换取多少个奖品。
分析
先要确保 ,然后是基本二分结构,结构还是讲一下吧:
- 二分会有起始的 和 。
- 循环一般用
while,条件一般为while(left <= right)。 - 在循环内部要用 来求 和 的中间值,即
middle = (left + right) / 2。 - 以上代码可优化成
middle = left = (right - left) / 2,这样可以确保不会溢出。 - 通过一个函数的返回值,去修改 或 的值,即
left = middle + 1或right = middle - 1。 - 二分因为每次减少一半的范围,所以时间复杂度为 。
输入加二分框架:
CPPint n, m, a, b, v;
cin >> n >> m >> a >> b;
if (n < m) {
swap(n, m);
}
if (a < b) {
swap(a, b);
}
v = a - b;
int left = 0, right = n;
int ans = 0;
while (left <= right) {
int middle = left + (right - left) / 2;
if (check(middle) == 1) {
ans = max(ans, middle);
left = middle + 1;
} else {
right = middle - 1;
}
}
接下来就是写 函数了。
把 作为参数传入,求出按当前比例分配的两个量 ,如果 超出上限 时,需要转换 和 ,而转换量为 ,最后判断以下 与 之间的关系,返回 0 或 1,在二分循环中做出相应修改,结束后输出答案即可。
注意
此题因 较大,需要使用
#define int long long。AC CDOE
CPP#include <bits/stdc++.h>
#define int long long //不开80分
using namespace std;
int n, m, a, b, v;
bool check(int middle) { //求解
int x = a * middle, y = b * middle; //按当前比例分配的总量
if (x > n) { //若x超过上限n时
int k = (x - n + v - 1) / v; //需要转换的量
x -= k * v, y += k * v; //等比例转换
}
if (x <= n && y <= m) { //最后判断
return 1;
}
return 0;
}
signed main() {
cin >> n >> m >> a >> b;
if (n < m) { //保证n>=m
swap(n, m);
}
if (a < b) { //保证a>=b
swap(a, b);
}
v = a - b; //修改
int left = 0, right = n; //二分l,r
int ans = 0;
while (left <= right) { //二分条件
int middle = left + (right - left) / 2; //二分mid
if (check(middle) == 1) { //两种情况
ans = max(ans, middle); //修改
left = middle + 1; //缩减范围
} else {
right = middle - 1; //缩减范围
}
}
cout << ans; //输出代码
return 0;
}
相关推荐
评论
共 7 条评论,欢迎与作者交流。
正在加载评论...