专栏文章

题解:P13013 [GESP202506 五级] 奖品兑换

P13013题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miozxu3k
此快照首次捕获于
2025/12/03 03:54
3 个月前
此快照最后确认于
2025/12/03 03:54
3 个月前
查看原文
非常不错的一道二分答案题目,整体不算太难。
思路如下:我们需要确定最多能兑换多少份奖品。兑换一份奖品可以使用两种方式:一种是使用 aa 张课堂优秀券和 bb 张作业优秀券,另一种是使用 bb 张课堂优秀券和 aa 张作业优秀券。
给出 nn 张课堂优秀券和 mm 张作业优秀券,我们需要找出最大的兑换份数 midmid ,使得存在非负整数 xxyy ,其中 x+y=midx+y=mid ,需要满足以下条件:
  • a×x+b×yna\times x + b \times y \le n
  • b×x+a×ymb\times x + a \times y \le m
使用二分法来寻找最大的 midmid 。二分范围的下界为 00 ,上界为 max(n,m)/min(a,b)+1 \max(n,m) / \min(a,b) + 1 ( 确保覆盖可能的解)。同时,检查函数中对于每个候选的 tt ,检查是否存在非负整数 x0xtx(0 \le x \le t) 满足:
  • (ab)×xnb×t(a - b)\times x \le n - b\times t
  • (ab)×xa×tm(a - b) \times x \ge a \times t - m
根据 aabb 的大小关系,分情况处理:
  • aa bb 相等时,只需验证 a×tna\times t \le n a×tm a\times t ≤ m
  • a>ba > b 时,计算 xx 的下界和上界,并检查是否存在整数 xx[0,t][0, t] 范围内。
  • a<ba < b 时,同样计算 xx 的下界和上界,并检查是否存在整数 xx[0,t][0, t] 范围内。
剩下就是二分答案的模板了,相信大家都可以看懂,上代码:
CPP
#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;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...