Gift Set 二分 数学
Posted 爷灬傲奈我何123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gift Set 二分 数学相关的知识,希望对你有一定的参考价值。
题意:
给定x,y个红,蓝气球,每次可以选择a个红气球,b个蓝气球,或者a个蓝气球,b个红气球,问最多能分成多少组。
思路:
不妨设a>b,不难发现这个题可以二分,即如果ans = x ,那么对于任意y<x都会存在方案让答案有解 假设第一种方案有k组,那么k要满足又要大于等于0并且小于等于当前组数,然后又有两个柿子生成,ak+b(mid-k)<=x && bk+a(mid-k)<=y,由此可以产生关于k的解,那么题目就转变为给你两个线段,两条线段是否相交。
这里有个坑点就是判断线段,如果不整除左端点要向上,右端点要向下。如果右端点是负数,还得减1,wa死我了。
代码:
// Problem: G. Gift Set
// Contest: Codeforces - Codeforces Round #725 (Div. 3)
// URL: https://codeforces.com/contest/1538/problem/G
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
typedef long long ll;
using namespace std;
#define int long long
int x,y,a,b;
bool check(int mid)
{
int l=ceill((a*mid-y)*1.0l/(a-b) );
int r=(x-b*mid)/(a-b);
if(x-b*mid<0)
return 0;
if(l>r) return 0;
int maxl=max(l,0ll);
int minr=min(r,mid);
return maxl<=minr;
}
signed main()
{
ios;
int t;
cin >> t;
while(t--)
{
cin >> x >> y >> a >> b;
if(a<b)
{
swap(a,b);
swap(x,y);
}
if(a==b){
cout<<min(x,y)/a<<endl;
continue;
}
int l = 0,r=1e9+100;
while(l<r)
{
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
以上是关于Gift Set 二分 数学的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 912 E.Prime Gift (折半枚举二分)