CF 1538 G. Gift Set (贪心+思维)

33 篇文章 0 订阅
22 篇文章 0 订阅

链接

题意:

Polycarp有x个红糖和y个蓝糖,现在他想用这些糖果做一些礼品盒(gift set),但规定每个礼品盒里必须有a个红糖、b个蓝糖或b个红糖、a个蓝糖。现在求他最多能做成多少个礼品盒。

分析:

首先我们会发现这个题有很多种方法:二分( O ( l o g ( n ) ) O(log(n)) O(log(n))),模拟( O ( 1 ) O(1) O(1)),模拟退火等,

二分:

既然他是最多能做多少,那么我们可以发现,答案满足单调性,那么我们直接二分答案就好了。
首先我们找到那个用的糖果更少,假设a的更少。那么我们枚举的答案,一定满足: x − a ∗ a n s > = 0 ; y − a ∗ a n s > = 0 ; x-a*ans>=0;y-a*ans>=0; xaans>=0;yaans>=0;这是肯定的,因为如果用的少的都不满足跟不用提多的了,然后我们看如果 a = b a=b a=b那么他一定是满足条件的,否则就是 a < b a<b a<b我们就要看 ( x − a ∗ a n s ) / ( b − a ) + ( y − a ∗ a n s ) / ( b − a ) > = a n s (x-a*ans)/(b-a)+(y-a*ans)/(b-a)>=ans (xaans)/(ba)+(yaans)/(ba)>=ans这样就是满足条件的,否则不满足。为什么那?其实就是用剩下的空变化一下成b,由a变成b需要加上 b − a b-a ba所以我们看有多少可以转化成b,如果比ans大或者相等那么这个ans是可以的,否则就不可以。

void solve(){
	scanf("%lld%lld%lld%lld", &n, &m, &a, &b);
    if(a>b) swap(a,b);
    ll l=0,r=1e9+7;
    while(l<r){
        ll mid=(l+r)/2;
        ll x=n,y=m;
        x-=a*mid;
        y-=a*mid;
        bool flag=(x>=0&&y>=0);
        if(b>a){///防止出现a=b导致除以负数
            if(x/(b-a)+y/(b-a)<mid) flag=0;
        }
        if(flag) l=mid+1;
        else r=mid;
    }
    cout<<l-1<<endl;
}

模拟( O ( 1 ) O(1) O(1))

我们让n<m,a<b
我们分析出来他其实就是那么 一些(a+b,a+b)这样的二元组,和一些(a,b)这样的二元组。
我们发现我们选一个二元组(a,b)会让(n,m)之间的差缩减(b-a).所以我们可以先选 m − n b − a \frac{m-n}{b-a} bamn个(a,b)剩下的可以全选(a+b,a+b);

如果我们最后选完(a+b,a+b),还剩的够再买一个(a,b)或者(b,a)这样的二元组,那么我们就需要在做一次贡献。

需要特判一下,a=b因为不能除以0.答案是( n a \frac{n}{a} an)

void solve()
{
    scanf("%lld%lld%lld%lld", &n, &m, &a, &b);    
    ///O(1)
    if(n>m) swap(n,m);
    if(a>b) swap(a,b);
    if(n<a||m<b) {
        puts("0");
        return ;
    }
    ll ca=m-n,cb=b-a;
    if(cb==0){
        printf("%lld\n",n/a);
        return;
    }
    ll num=min(ca/cb,min(n/a,m/b));
    n-=num*a;m-=num*b;
    ll ans=num+min(n,m)/(a+b)*2;
    if(n>=a&&m>=b) n-=a,m-=b,num++;
    printf("%lld\n",max(ans,num+min(n,m)/(a+b)*2));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值