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;
    
} 
原文地址:https://www.cnblogs.com/tombraider-shadow/p/12390017.html