专栏文章
题解:P13013 [GESP202506 五级] 奖品兑换
P13013题解参与者 19已保存评论 19
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 19 条
- 当前快照
- 1 份
- 快照标识符
- @mip0c3q0
- 此快照首次捕获于
- 2025/12/03 04:05 3 个月前
- 此快照最后确认于
- 2025/12/03 04:05 3 个月前
前言
一道很好的二分练手题。
题目内容
题目分析
我们假设用第一种方式兑换了 次,用第二种方式兑换了 次,则总次数 ,并且满足 和 ,且 与 都为非负整数。
因为每次兑换至少消耗 张课堂优秀券和 张作业优秀券(当 时),所以 的上界为 。
对于给定的 ,检查是否有 (第一种方式兑换了 次,则第二种方式兑换了 次)满足:
整理得:
计算 的可行区间,如果非空则 可行。
边界处理:
- 当 时,直接记录答案。
- 当 时,先计算总券数是否够,然后计算 的区间。
上代码(知道你们直接看这个)
CPP#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define fst ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define prq priority_queue
#define uns unordered_set
#define freopen freopen(".in","r",stdin);freopen(".out","w",stdout);
const int P = 998244353;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6+10, M = 1e8 + 10;
int __lcm(int a,int b){return a/__gcd(a,b)*b;}
int n,m,a,b;
int ans=0;
signed main()
{
fst
cin>>n>>m>>a>>b;
if(a>b)swap(a,b);//确保a<=b
int l=0,r=min(n/a,m/a);//左右区间
while(l<=r){
int mid=(l+r)/2;
if(a==b){
ans=mid;
l=mid+1;
}//情况1
else{
if((a+b)*mid>n+m){
r=mid-1;
continue;
}
int mi=0;
if(b*mid>n){
mi=(b*mid-n+b-a-1)/(b-a);//左端点
}
int ma=(m-a*mid)/(b-a);
ma=min(ma,mid);//右端点
if(ma>=0&&mi<=ma){
ans=mid;
l=mid+1;
}
else{
r=mid-1;
}
}//情况2
}
cout<<ans;
return 0;
}
UPD
2025.7.2 感谢 @pika_ 大佬指出的错误。
相关推荐
评论
共 19 条评论,欢迎与作者交流。
正在加载评论...