• [Educational Codeforces Round 82 (Rated for Div. 2)] D. Fill The Bag (二进制拆分,贪心)


    [Educational Codeforces Round 82 (Rated for Div. 2)] D. Fill The Bag (二进制拆分,贪心)

    D. Fill The Bag

    time limit per test

    2 seconds

    memory limit per test

    256 megabytes

    input

    standard input

    output

    standard output

    You have a bag of size nn. Also you have mm boxes. The size of ii-th box is aiai, where each aiai is an integer non-negative power of two.

    You can divide boxes into two parts of equal size. Your goal is to fill the bag completely.

    For example, if n=10n=10 and a=[1,1,32]a=[1,1,32] then you have to divide the box of size 3232 into two parts of size 1616, and then divide the box of size 1616. So you can fill the bag with boxes of size 11, 11 and 88.

    Calculate the minimum number of divisions required to fill the bag of size nn.

    Input

    The first line contains one integer tt (1≤t≤10001≤t≤1000) — the number of test cases.

    The first line of each test case contains two integers nn and mm (1≤n≤1018,1≤m≤1051≤n≤1018,1≤m≤105) — the size of bag and the number of boxes, respectively.

    The second line of each test case contains mm integers a1,a2,…,ama1,a2,…,am (1≤ai≤1091≤ai≤109) — the sizes of boxes. It is guaranteed that each aiai is a power of two.

    It is also guaranteed that sum of all mm over all test cases does not exceed 105105.

    Output

    For each test case print one integer — the minimum number of divisions required to fill the bag of size nn (or −1−1, if it is impossible).

    Example

    input

    Copy

    3
    10 3
    1 32 1
    23 4
    16 1 4 1
    20 5
    2 1 16 1 8
    

    output

    Copy

    2
    -1
    0
    

    题意:

    t组数据,每一组数据给定一个整数n,以及m个整数(a[i]),保证(a[i])为2的次幂

    代表有一个尺寸为n的箱子,整数a[i]代表一个尺寸为a[i] 的物品,每一个物品可以拆分为2个(frac{a[i]}{2}),由拆分得到的物品可以继续再拆分。

    问最小需要拆分多少次能使箱子装满?如果装不满答案为-1

    思路:

    如果(sum_{i=1}^n a_i < n) 答案为-1,否则可以装满。

    我们考虑从小到大物品尺寸:

    对于物品尺寸为(2^i) 的情况由以下3种:

    1、如果n的二进制表示法中的第i位 等于0,那么我们就用不到尺寸为(2^i)的物品了,我们考虑将其“合并“为(2^{i+1})

    2、如果n的二进制表示法中的第i位 等于1,且我们有至少一个尺寸为(2^i)的物品,然后将其装入盒子,将剩下的(2^i)“合并”为(2^{i+1})

    3、如果n的二进制表示法中的第i位 等于1,我们没有尺寸为(2^i)的物品,然后考虑必须去拆一个更大尺寸(2^x)的物品来装入盒子。答案加上(x-i),再此之后,我们只需要继续该算法从(2^x)开始。

    代码:

    
    /*** TEMPLATE CODE * * STARTS HERE ***/
    ll n;
    int m;
    ll a[400];
    ll b[400];
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        int t;
        t = readint();
        while (t--)
        {
            repd(i, 0, 61)
            {
                a[i] = 0;
                b[i] = 0;
            }
            n = readll();
            m = readint();
            for (int i = 60; i >= 0; --i)
            {
                if (n & (1ll << i))
                {
                    a[i]++;
                }
            }
            repd(i, 1, m)
            {
                ll x = readint();
                for (int j = 30; j >= 0; --j)
                {
                    if (x & (1 << j))
                    {
                        b[j]++;
                    }
                }
            }
            int ans = 0;
            int isok = 1;
            int flag;
            repd(i, 0, 60)
            {
                if (a[i])
                {
                    if (b[i])
                    {
                        b[i]--;
                        b[i + 1] += b[i] / 2;
                    } else
                    {
                        flag = 0;
                        repd(j, i + 1, 60)
                        {
                            if (b[j])
                            {
                                flag = 1;
                                ans += j - i;
                                i = j - 1;
                                b[j]--;
                                break;
                            }
                        }
                        if (!flag)
                        {
                            isok = 0;
                        }
                    }
                } else
                {
                    b[i + 1] += b[i] / 2;
                }
            }
            if (isok)
            {
                printf("%d
    ", ans);
            } else
            {
                printf("-1
    ");
            }
    
        }
    
        return 0;
    }
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    iOS小技巧总结,绝对有你想要的
    Myeclipse for Mac快捷键
    iOS开发如何学习前端
    iOS应用支持IPV6,就那点事儿
    App Store审核被拒的23个理由
    43个优秀的Swift开源项目
    ExtJs组件之间的相互访问,访问机制
    hibernate or连接查询内容/criteria动态或连接查询/disjunction/其他查询条件
    hibernate如何解除关系———只删除多方保留一方
    java如何操作视图
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/12310138.html
Copyright © 2020-2023  润新知