Codeforces D. Fill The Bag
D. Fill The Bag
题目链接:https://codeforces.com/contest/1303/problem/D
解题思路:位运算,暴力求解。我们知道每一个盒子都可以分成1。因此,当所有盒子的总和小于n的时候,这个时候是不可能的。
然后就是可能的时候的求解。我们从最低位向最高位求解。我们假设是第i位,若n的第i位是0话,我们就不需要为2i的盒子,这时候我们
只需要向上合并。然后如果是1的话,若存在为2的i次方的盒子,我们就可以用来填充这一位。然后奖剩余的盒子合并。若没有的话
只能将更重的盒子向下分解。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+10; ll index[maxn],num[maxn],a[maxn]; int main() { int t; cin>>t; while(t--) { ll n,m; ll sum=0; cin>>n>>m; for(int i=1 ;i<= m;i++) { cin>>a[i]; sum+=a[i]; } if(sum<n) { cout<<"-1"<<endl; continue; } for(int i=1;i<=m;i++) { index[(int)(log2(a[i]))]++; } ll n1=n,cnt=0; while(n1) { if(n1%2) num[cnt]++; cnt ++ ; n1/=2; } ll ans=0; for(int i=0 ;i<70;i++) { if(num[i]) { if(index[i]) { index[i+1]+=(index[i]-1)/2; } else { for(int j=i+1;j<70;j++) { if(index[j]) { ans+=j-i; index[j]--; for(int k=j-1;k>i;k--) index[k]++; break; } } } } else { index[i+1]+=index[i]/2; } } memset(index,0,sizeof(index)); memset(num,0,sizeof(num)); cout<<ans<<endl; } return 0; }