Magic Powder - 1、2(二分查找)

题目:

This problem is given in two versions that differ only by constraints. If you can solve this problem in large constraints, then you can just write a single solution to the both versions. If you find the problem too difficult in large constraints, you can write solution to the simplified version only.

Waking up in the morning, Apollinaria decided to bake cookies. To bake one cookie, she needs n ingredients, and for each ingredient she knows the value ai — how many grams of this ingredient one needs to bake a cookie. To prepare one cookie Apollinaria needs to use all n ingredients.

Apollinaria has bi gram of the i-th ingredient. Also she has k grams of a magic powder. Each gram of magic powder can be turned to exactly 1 gram of any of the n ingredients and can be used for baking cookies.

Your task is to determine the maximum number of cookies, which Apollinaria is able to bake using the ingredients that she has and the magic powder.

题意:

这个问题给出了两个版本,不同的地方仅仅在于约束条件。如果您可以在较大的约束条件下解决这个问题,那么您就可以为两个版本编写一个解决方案。如果你发现问题在大的约束条件下太难,你可以只写简化版本的解决方案。

早晨醒来,阿波利纳利亚决定烤饼干。为了烤一块饼干,她需要n种原料,她知道每一种原料的值ai(烤一块饼干需要多少克这种原料)。为了准备一块饼干,Apollinaria需要使用所有n种材料。

Apollinaria含有2克第i种成分。她还有k克魔法粉。每克神奇粉末可以转化成n种原料中的1克,可以用来烤饼干。

你的任务是确定Apollinaria使用她拥有的原料和魔法粉能够烘烤的饼干的最大数量。

输入

输入的第一行包含两个正整数n和k(1≤n, k≤1000)——原料的种类数和魔粉的克数。

第二行包含序列a1, a2,…, an(1≤ai≤1000),其中第i个数字等于第i种原料的克数,代表烘烤一块饼干所需的原料。

第三行包含序列b1, b2,…, bn(1≤bi≤1000),其中第i个数字等于第i个成分的克数,代表Apollinaria拥有的配料。

输出

打印出最大数量的饼干,Apollinaria将能够使用她拥有的材料和魔法粉末烘焙。

测试样例:

输入1

3 1
2 1 4
11 3 16

输出1

4

输入2

4 3
4 3 5 6
11 12 14 20

输出2

3

输入3

1 1000000000
1
1000000000

输出3

2000000000

输入4

10 1
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000
1 1 1 1 1 1 1 1 1 1

输出4

0

分析:

题目主要意思就是:做饼干,输入饼干所需原料种类,然后输入拥有的各种类的原料数,同时输入拥有的魔法粉末数量,魔法粉末可以等量变成任何原料。求最多可以做出来多少饼干。

Magic Powder - 1

在 Magic Powder - 1中,要求的测试样例比较小,因此不用考虑时间复杂度。思路就是循环,每循环一次饼干数+1,每次循环中判断原料缺少的数量,若小于魔法粉末数量,则魔法粉末数量减去缺少数量,进行下次循环;直到魔法粉末数量小于缺少原料数量。

Magic Powder - 2

在 Magic Powder - 2中,要求的测试样例比较大,因此需要考虑时间复杂度。考虑到测试样例比较大,所以我们可以使用二分查找的思路进行计算。

因为数据比较大的原因,这道题只能采用 二分+模拟 来进行。将left=0,right=2000000010(题目给出的数据的范围最大值)。循环对饼干数进行查找,同时需判断缺少原料总数是否大于魔法药粉数,若大于,则跳出循环,并输出left+1,即为饼干数。

参考代码(c语言实现)

Magic Powder - 1(暴力模拟)

#include<stdio.h>
#define N 1000010
long long  n, k;
long long a[N], b[N]; //a为做一个饼干需要的原料,b为拥有的原料
long long sum;
int main()
{
    scanf("%lld%lld", &n, &k);
    for (int i = 0; i < n; i++)
        scanf("%lld", &a[i]);
    for (int i = 0; i < n; i++)
        scanf("%lld", &b[i]);
    for(sum=0;;sum++)
    {
        int c = 0;
        for (int i = 0; i < n; i++)
            b[i] -= a[i];
        for (int i = 0; i < n; i++)
            if (b[i] < 0) {
                c =c -b[i];
                b[i] = 0;
            }
        if (c > k)  //当缺的原料多于magic粉时,则不用进行下面的判断
        {
            printf("%lld\n", sum); break;
        }
        k -= c;
    }
    return 0;
}

Magic Powder - 1(二分+模拟)

#include<stdio.h>
#define N 1000000
long long  n, k, sum;
long long a[N], b[N], c[N]; //a为做一个饼干需要的原料,b为拥有的原料,c为每个原料缺少的个数
int solve(int mid);
int main()
{
    scanf("%lld%lld", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &b[i]);
    int mid, l = 0, r = 10000000;
    while (r >= l)  //二分 + 模拟
    {
        mid = (l + r) / 2;
        for (int i = 1; i <= n; i++)
            c[i] = b[i] - mid * a[i];
        int num = 0;
        for (int i = 1; i <= n; i++)
            if (c[i] < 0) num += -c[i];  //num为缺少的原料总数
        if (num <= k) {
            sum = mid;
            l = mid + 1;
        }
        else
            r = mid - 1;
    }
    printf("%lld\n", sum);
    return 0;
}

Magic Powder - 2

#include<stdio.h>
#define N 100010
long long a[N], b[N];
int main()
{
    long long n, k, i;
    scanf("%lld%lld", &n, &k);
    for (i = 0; i < n; i++)
        scanf("%lld", &a[i]);
    for (i = 0; i < n; i++)
        scanf("%lld", &b[i]);

    long long l = 0, r = 2000000010;
    long long mid ,sum;
    while (l <= r)
    {
        sum = 0;
        mid = (l + r) / 2;
        for (i = 0; i < n; i++)
        {
            if (mid * a[i] > b[i])
                sum += (mid * a[i] - b[i]);  //sum为缺少的原料总和
            if (sum > k)
                break;
        }
        if (sum <= k) l = mid + 1;  //向右寻找,l=mid+1(mid不用再判断)
        else 
            r = mid - 1;
    }
    printf("%lld\n", l - 1);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值