D. Fill The Bag

D. Fill The Bag
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You have a bag of size n. Also you have m boxes. The size of i-th box is ai, 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 n=10 and a=[1,1,32] then you have to divide the box of size 32 into two parts of size 16, and then divide the box of size 16. So you can fill the bag with boxes of size 1, 1 and 8.

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

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

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

The second line of each test case contains m integers a1,a2,…,am (1≤ai≤109) — 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 105.

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

Example
inputCopy
3
10 3
1 32 1
23 4
16 1 4 1
20 5
2 1 16 1 8
outputCopy
2
-1
0

題意:
給你一個序列,問你能不能組合出n,你可以把其中一個數變成他的一半,問你最少的操作次數。

思路:
首先輸入的時候處理一下x,累加後看和s是否大於m,如果小於輸出-1。
邊輸入邊預處理,cnt[]爲原序列中的第i位是否有數。
把m拆成二進制,從低位到高位枚舉,注意如果把16拆成4的話,cnt[3 (2^3=8)]也要更新,就是更新拆分的路徑。

代碼:

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
//#define ll unsigned long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-6
#define pi acos(-1)
#define mea (memset(a,0,sizeof(a)))
#define myit set<ll>::iterator
#define mysets multiset<ll>
#define myits multiset<ll>::iterator
#define v30 (1<<30)-1
#define all(x) (x).begin(),(x).end()
#define maxs *s.rbegin()
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mid ((a[k].r+a[k].l)>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define kl k<<1
#define kr k<<1|1
using namespace std;
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
using namespace std;
 
const int manx=1e5+10;
 
ll cnt[manx];
int main()
{
	ll p=read();
	while(p--){
        ll m=read(),n=read(),s=0,ans=0;
        for(int i=0;i<=30;i++) cnt[i]=0;
        for(int i=1;i<=n;i++){
            ll x=read(),tot=0;
            s+=x;
            while(x>1) tot++,x>>=1;
            cnt[tot]++;
        }
        if(s<m){
            put3();
            continue;
        }
        s=0;
        for(int i=0;i<=62;i++){
            if( (1<<i) & m )  /*cout<<m<<" "<<(1<<i)<<endl,*/s--;
            if(s<0){
                int k=i;
                while(!cnt[k]) cnt[k++]=1;
                cnt[k]--;
             //   cout<<k<<" "<<i<<endl;
                ans+=k-i;
                s=0;
            }
            s+=cnt[i];
            s>>=1;
        }
        cout<<ans<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章