D. Fill The Bag(思维+二进制贪心+模拟)

https://codeforces.com/problemset/problem/1303/D


思路:

平时大到小贪心,这次小到大。一个变量记录此时的剩余总量。看能否给与当前位。>=必然是可以给与的。

假设当前位为2^pj,剩余总量的p^i(i<=j)  ,如果存在==j的,肯定能给。假设全部i<j,剩余总量还能构造出这个2^j吗?肯定可以。

第一个都是二进制。

第二个 2^pi1+2^pi2+2^pi3+......>=2^pj;  对这个不等式不断/2;最后等式右边必然到0,等式左边必然>=0,如果不为0,剩下那部分就是多出来的,被消去的就是刚好构造成这个2^j的。

然后小到大,剩余总量对于当前位够了就够,不够从最近的大于这一位的往前找,分解了然后加上分解后数量。进行模拟。

Note:ai<=1e9,但是我开到61才过(调了好一会

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL p[100],cnt[100];
map<LL,LL>map1;
LL a[maxn];
int main(void){
   cin.tie(0);std::ios::sync_with_stdio(false);
   p[0]=1;
   for(LL i=1;i<=60;i++) p[i]=p[i-1]*2;
   LL t;cin>>t;
   while(t--){
      LL n,m;cin>>n>>m;
      map1.clear();
      for(LL i=60;i>=0;i--){
          cnt[i]=0;
          if(n&p[i]) cnt[i]=1,n-=p[i];
      }
      for(LL i=1;i<=m;i++){
          cin>>a[i];
          for(LL j=0;j<=31;j++){
              if(a[i]&p[j]) {map1[j]++;break;}
          }
      }
      ///低位往高位
      bool flag=1;
      LL sum=0;///剩余的总和
      LL ans=0;
      for(LL i=0;i<=60;i++){
            sum+=(p[i])*map1[i];
            if(cnt[i]){
               if(sum>=p[i]){
                    sum-=p[i];
               }
               else{
                  for(LL j=i+1;j<=61;j++){///..?不是ai<=1e9
                      if(map1[j]>0){
                         map1[j]--;
                         ans+=j-i;
                         for(LL k=i;k<=j-1;k++) sum+=p[k];
                         break;
                      }
                      if(j==61) flag=0;
                  }
               }
            }
            if(flag==0) break;
      }
      if(flag) cout<<ans<<"\n";
      else cout<<"-1"<<"\n";
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/115407295
今日推荐