CZK 的饮料店

【题目描述】

一天,小学生 cyx 向你请教了一道他不会做的小学数学题,你瞄了一眼题目,发现题目长下面这样。

czk 老板开了个饮料连锁店,连锁店共有 n 家,出售的饮料种类相同。

为了促销,czk 决定让每家连锁店开展赠送活动。具体来说,在第 i 家店,顾客可以用 a个饮料瓶兑换到 b瓶饮料和 1 个纪念币(注意不足 a个饮料瓶则不能兑换)。

一家店可以兑换多次,兑换得到的饮料瓶还可以继续用于兑换。

你买了 s 瓶饮料,想知道用这 s 瓶饮料最多可以兑换到多少个纪念币。

请你帮小学生 cyx 回答这个简单的小学数学题。

【输入格式】

从文件 maths.in 中读入数据。

输入第一行为两个整数 n, s,分别表示连锁店的数量和你买的的饮料瓶数。

接下来 n 行,每行两个整数 ai, bi,描述第 i 家饮料店的赠送活动。

【输出格式】

输出到文件 maths.out 中。

输出一行一个整数,表示小 C 最多能兑换到的纪念币数量。若小 C 能兑换到无限多个纪念币,则输出 -1 。

【输入样例】

3 11

4 1

5 2

8 4

【输出样例】

3

【样例解释】

最多兑换到 3 个纪念币。兑换过程如下:

(1)在第 1 家店用 4 瓶换 1 瓶,此时剩 11-4+1=8 瓶,有 1 个纪念币;

(2)在第 1 家店用 4 瓶换 1 瓶,此时剩 8-4+1=5 瓶,有 2 个纪念币;

(3)在第 2 家店用 5 瓶换 2 瓶,此时剩 5-5+2=2 瓶,有 3 个纪念币;

剩余的饮料瓶无法在任何店兑换,因此最多兑换到 3 个纪念币。

【数据规模及约定】

对于 30%的数据,0 ≤ n ≤ 10,0 ≤ s ≤ 20 ;

对于 50%的数据,0 ≤ n ≤ 1000,0 ≤ s ≤ 100000;

对于 100%的数据,0 ≤ n ≤ 100000,0 ≤ s ≤ 1019,0 ≤ a≤ 1019,0 ≤ b≤1019 。


 

【思路】

很明显的可以用贪心来做这道题。

①首先,对于可以无限兑换饮料的情况:如果满足 需要的饮料瓶数不多于获得的饮料瓶数(即 ai ≤ bi),且自己已经拥有的饮料瓶足够兑换( s ≥ a ,就可以直接输出 -1 。

②如果不能无限兑换饮料,就考虑贪心。

可以把每一次的兑换饮料看作是一种损失,大小为 ai - b。因为拥有的饮料瓶数量 s 不会增加,为了能够更多次地兑换饮料,需要再能够兑换的范围内将每一次兑换的损失控制得尽量小。

将每一个店的损失( ai - b)作为第一关键字,每个店的兑换的需求(ai)作为第二关键字,用 sort 从小到大排序。(其中,对于 ai - bi 相等的,则可以按照任意顺序排序)。统计答案。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef unsigned long long ull;
const int maxn=100005;
struct hh
{
    ull a,b;
}t[maxn];
ull n,s;
ull ans,cnt;
inline bool cmp(const hh&x,const hh&y)
{
    return x.a-x.b<y.a-y.b||x.a-x.b==y.a-y.b&&x.a<y.a; 
}
int main()
{
    freopen("maths.in","r",stdin);
    freopen("maths.out","w",stdout);
    std::cin>>n>>s;
    for(ull i=1;i<=n;i++)
    {
        std::cin>>t[i].a>>t[i].b;
    }
    sort(t+1,t+n+1,cmp);
    for(ull i=1;i<=n;i++)
        if(t[i].a-t[i].b<=0 && t[i].a<=s)
        {
            printf("-1\n");
            return 0;
        }
    for(ull i=1;i<=n;i++)
    {
        if(s>=t[i].a)
        {
            cnt=(s-t[i].a)/(t[i].a-t[i].b)+1;
            s-=(t[i].a-t[i].b)*cnt;
            ans+=cnt;
        }
    }
    std::cout<<ans<<endl;
return 0;
}

 

转载于:https://www.cnblogs.com/lck-lck/p/9755362.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值