Description:
You have a bag of size . Also you have m boxes. The size of box is , where each ai 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 and then you have to divide the box of size 32 into two parts of size , and then divide the box of size 16. So you can fill the bag with boxes of size and .
Calculate the minimum number of divisions required to fill the bag of size n.
Input
The first line contains one integer — the number of test cases.
The first line of each test case contains two integers and — the size of bag and the number of boxes, respectively.
The second line of each test case contains m integers — the sizes of boxes. It is guaranteed that each ai is a power of two.
It is also guaranteed that sum of all m over all test cases does not exceed .
Output
For each test case print one integer — the minimum number of divisions required to fill the bag of size (or −1, if it is impossible).
Example
input
3
10 3
1 32 1
23 4
16 1 4 1
20 5
2 1 16 1 8
output
2
-1
0
题意:
给你一个序列,问你能不能组合出
,你可以把其中一个数变成两个大小相等的部分,问你最少的操作次数。
一种情况不能组成那就是全部加起来还是小于
,然后我们就开始贪心,从大到小如果这个数比背包质量小那就直接放进去,如果比背包质量大并且剩下的质量填不满背包我们就操作一次,否则我们舍弃这个物品。
AC代码:
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stack>
#include <queue>
using namespace std;
#define sd(n) scanf("%d", &n)
#define sdd(n, m) scanf("%d%d", &n, &m)
#define sddd(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n, m) printf("%d %d\n", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n, m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld", &n)
#define sldd(n, m) scanf("%lld%lld", &n, &m)
#define slddd(n, m, k) scanf("%lld%lld%lld", &n, &m, &k)
#define sf(n) scanf("%lf", &n)
#define sc(n) scanf("%c", &n)
#define sff(n, m) scanf("%lf%lf", &n, &m)
#define sfff(n, m, k) scanf("%lf%lf%lf", &n, &m, &k)
#define ss(str) scanf("%s", str)
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define mem(a, n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define mod(x) ((x) % MOD)
#define gcd(a, b) __gcd(a, b)
#define lowbit(x) (x & -x)
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
inline int read()
{
int ret = 0, sgn = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
sgn = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
ret = ret * 10 + ch - '0';
ch = getchar();
}
return ret * sgn;
}
inline void Out(int a) //Êä³öÍâ¹Ò
{
if (a > 9)
Out(a / 10);
putchar(a % 10 + '0');
}
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b)
{
return a * b / gcd(a, b);
}
///快速幂m^k%mod
ll qpow(ll a, ll b, ll mod)
{
if (a >= mod)
a = a % mod + mod;
ll ans = 1;
while (b)
{
if (b & 1)
{
ans = ans * a;
if (ans >= mod)
ans = ans % mod + mod;
}
a *= a;
if (a >= mod)
a = a % mod + mod;
b >>= 1;
}
return ans;
}
// 快速幂求逆元
int Fermat(int a, int p) //费马求a关于b的逆元
{
return qpow(a, p - 2, p);
}
///扩展欧几里得
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
int g = exgcd(b, a % b, x, y);
int t = x;
x = y;
y = t - a / b * y;
return g;
}
///使用ecgcd求a的逆元x
int mod_reverse(int a, int p)
{
int d, x, y;
d = exgcd(a, p, x, y);
if (d == 1)
return (x % p + p) % p;
else
return -1;
}
///中国剩余定理模板0
ll china(int a[], int b[], int n) //a[]为除数,b[]为余数
{
int M = 1, y, x = 0;
for (int i = 0; i < n; ++i) //算出它们累乘的结果
M *= a[i];
for (int i = 0; i < n; ++i)
{
int w = M / a[i];
int tx = 0;
int t = exgcd(w, a[i], tx, y); //计算逆元
x = (x + w * (b[i] / t) * x) % M;
}
return (x + M) % M;
}
ll n;
ll m;
const int N = 1e5 + 10;
ll a[N], sum, ans;
int main()
{
int t;
sd(t);
while (t--)
{
sldd(n, m);
sum = 0;
rep(i, 1, m)
{
sld(a[i]);
sum += a[i];
}
if (sum < n)
{
puts("-1");
continue;
}
sort(a + 1, a + m + 1);
ans = 0;
while (m)
{
if (a[m] <= n)
{
n -= a[m];
sum -= a[m--];
}
else if (sum - a[m] < n)
{
a[m] /= 2;
a[m + 1] = a[m];
m++;
ans++;
}
else
sum -= a[m--];
//cout << m << " " << a[m] << endl;
}
pld(ans);
}
return 0;
}