题目:http://codeforces.com/contest/1303/problem/D
题意:给定数n和m个数
a
i
a_i
ai(都是2的幂次),这m个数可以进行裂分成更小的2的幂次数,问最少需要裂分多少次,才能找到若干数,刚好凑成数n。其中
1
<
=
n
<
=
1
e
18
,
1
<
=
m
<
=
1
e
5
,
1
<
=
a
i
<
=
1
e
9
1<=n<=1e18,1<=m<=1e5,1<=a_i<=1e9
1<=n<=1e18,1<=m<=1e5,1<=ai<=1e9
思路:从小到大枚举位,多余的二进制位可以凑成高位,不足位时,向高位借数。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,sum;
int cnt[62],m;
int main() {
int t;scanf("%d",&t);
while(t--) {
scanf("%I64d%d",&n,&m);
sum = 0;
memset(cnt,0,sizeof(cnt));
for(int i = 1,x;i <= m;i++) {
scanf("%d",&x);//__builtin_ctz返回后面0的个数
cnt[__builtin_ctz(x)]++;
sum += x;
}
if(sum < n) {
puts("-1");continue;
}
int ans = 0;
for(int i = 0,j;i <= 60;i++) {
if(n&(1LL<<i)) {
j = i;
while(!cnt[j]) j++;
while(j!=i) {
cnt[j]--;
cnt[j-1] += 2;
ans++;j--;
}
cnt[i]--;
}
cnt[i+1] += cnt[i]/2;
}
printf("%d\n",ans);
}
}