[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\n", ans);
        } else
        {
            printf("-1\n");
        }

    }

    return 0;
}



posted @ 2020-02-14 23:09  茄子Min  阅读(177)  评论(0编辑  收藏  举报