Educational Codeforces Round 82 (Rated for Div. 2)D(模拟)
从低位到高位枚举,当前位没有就去高位找到有的将其一步步拆分,当前位多余的合并到更高一位
1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 int a[100007]; 5 int sum[67],num[67]; 6 int main(){ 7 ios::sync_with_stdio(false); 8 cin.tie(NULL); 9 cout.tie(NULL); 10 int t; 11 cin>>t; 12 while(t--){ 13 memset(sum,0,sizeof(sum)); 14 memset(num,0,sizeof(num)); 15 long long n; 16 int m; 17 cin>>n>>m; 18 long long x=n; 19 int cnt2=0; 20 while(n){ 21 if(n&1) 22 ++sum[cnt2];//将n转化为二进制 23 n/=2; 24 ++cnt2; 25 } 26 long long res=0; 27 for(int i=1;i<=m;++i){ 28 cin>>a[i]; 29 res+=a[i]; 30 int cnt=-1; 31 while(a[i]){ 32 a[i]/=2; 33 ++cnt; 34 } 35 ++num[cnt];//将a[i]转化为二进制 36 } 37 if(res<x){ 38 cout<<"-1\n"; 39 continue; 40 } 41 long long ans=0; 42 for(int i=0;i<61;++i){//从低位向高位枚举 43 if(sum[i]){ 44 if(num[i]) 45 --num[i];//如果有对应a[i]直接取 46 else{ 47 for(int j=i+1;j<61;++j){//没有的话就找到最近的一个a[i] 48 if(num[j]){ 49 --num[j];//把它一步步拆掉,直到二进制下i位有一个可取 50 for(int k=i;k<j;++k){ 51 ++num[k]; 52 } 53 ans+=j-i;//一共拆了j-i次 54 break; 55 } 56 } 57 } 58 } 59 num[i+1]+=num[i]/2;//多余的a[i]向上合并成为更大的a[i+1] 60 } 61 cout<<ans<<"\n"; 62 } 63 return 0; 64 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)