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 }

猜你喜欢

转载自www.cnblogs.com/ldudxy/p/12308043.html