Codeforces Round #725 (Div. 3) G. Gift Set

链接

https://codeforces.com/contest/1538/problem/G

题意

有红色糖果 $x$ 个,蓝色糖果 $y$ 个。

可以将 $a$ 个红色糖果和 $b$ 个蓝色糖果或 $b$ 个红色糖果和 $a$ 个蓝色糖果打包成礼物。

求最多打包多少个礼物。

思路

设 $n$ 为最大礼物数量,显然礼物数量满足二分性。

若 $a=b$ ,$n=\lfloor\frac{min(x,y)}{a}\rfloor$。

否则,设 $a>b$,设第一种礼物数量为 $k$,那么第二种礼物数量为 $n-k$。

$
\begin{cases}
ak+b(n-k)\le x \
a(n-k)+bk \le y \
n \ge 0
\end{cases}
\longrightarrow
\begin{cases}
k \le \lfloor\frac{x-bn}{a-b}\rfloor \
k \ge \lceil\frac{y-an}{b-a}\rceil \
k \ge 0 \
k \le n
\end{cases}
$

若 $k$ 满足上述要求,则存在一种方式打包成 $n$ 个礼物,二分即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long double LD;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VPII;
// head
LL x,y,a,b;
bool check(LL mid) {
return max(0ll,(LL)ceil(1.0*(y-a*mid)/(b-a)))<=min(mid,(LL)floor(1.0*(x-b*mid)/(a-b)));
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;cin>>T;
while(T--) {
cin>>x>>y>>a>>b;
if(a==b) cout<<min(x,y)/a<<'\n';
else {
if(a<b) swap(a,b);
LL l=0,r=1e9;
while(l<r) {
LL mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<'\n';
}
}
return 0;
}