题目链接:点击这里
题目大意:
有
x
x
x 个红球,
y
y
y 个蓝球,一组物品由
a
a
a 个红球
b
b
b 个蓝球 或者
a
a
a 个蓝球
b
b
b 个红球组成,求这
x
x
x 个红球和
y
y
y 个蓝球最多能凑成多少组物品
题目分析:
设第一种组合和第二种组合的数目分别为
m
,
n
m,n
m,n ,题目转换为求
m
+
n
m+n
m+n 的最大值,其中
m
,
n
m,n
m,n 受如下了两个不等式限制:
a
∗
m
+
b
∗
n
≤
x
a*m+b*n \le x
a∗m+b∗n≤x
a
∗
n
+
b
∗
m
≤
y
a*n+b*m \le y
a∗n+b∗m≤y
m
+
n
m+n
m+n 显然具有单调性,所以可以考虑二分,接下来问题转化为如何
c
h
e
c
k
check
check :
设
c
n
t
=
m
+
n
cnt=m+n
cnt=m+n ,第一组有
k
k
k 中,此情况下有如下限制:
a
∗
k
+
b
∗
(
c
n
t
−
k
)
≤
x
a*k+b*(cnt-k)\le x
a∗k+b∗(cnt−k)≤x 即
k
≤
x
−
b
∗
c
n
t
a
−
b
k\le \frac {x-b*cnt}{a-b}
k≤a−bx−b∗cnt
a
∗
(
c
n
t
−
k
)
+
b
∗
k
≤
y
a*(cnt-k)+b*k\le y
a∗(cnt−k)+b∗k≤y 即
k
≥
y
−
a
∗
c
n
t
b
−
a
k\ge \frac{y-a*cnt}{b-a}
k≥b−ay−a∗cnt
0
≤
k
≤
c
n
t
0\le k\le cnt
0≤k≤cnt
a
>
b
a> b
a>b (保证不等号方向)
如果不等式有交集,那么就有解,交集为空就是无解
注意判断不等号满足时是上取整还是下取整
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
#define int ll
using namespace std;
inline int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 2e3+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int x,y,a,b;
bool check(int cnt)
{
if(a == b) return cnt <= min(x/a,y/b);
int l = ceil(1.0*(y-a*cnt)/(b-a));
int r = floor(1.0*(x-b*cnt)/(a-b));
l = max(0ll,l),r = min(r,cnt);
return l <= r;
}
signed main()
{
int t = read();
while(t--)
{
x = read(),y = read(),a = read(),b = read();
if(a < b) swap(a,b);
int l = 0,r = max(x/a,y/b),ans = -1;
while(l <= r)
{
int mid = l+r>>1;
if(check(mid)) l = mid+1,ans = mid;
else r = mid-1;
}
printf("%d\n",ans);
}
return 0;
}