I

题解:
注意这里的数组a中的元素,全部都是2的整数幂。然后有二进制可以拼成任意数。只要一堆2的整数幂的和大于x,x也是2的整数幂,那么那一堆2的整数幂一定可以组成x。

思路:位运算,对每一位,如果该位置i是1的话,先考虑从0到该位置的,数组a的和,如果比(1<<i)的话,那么可以拼接,否则的话,需要从高位向下除,也就是从i+1位到58位,找到第一个再某一位置j上不为0的数

然后需要降j-i次幂。然后从j~i,每一位上数的个数都要+1。并且累加答案ans+=j-i;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p[100];
void solve(){
    memset(p,0,sizeof p);
    ll n,m;
    cin>>n>>m;
    ll x;
    ll sum=0;
    for(ll i=1;i<=m;i++){
        cin>>x;
        sum+=x;
        ll j=0;
        while(!((x>>j)&1)) j++;
        p[j]++;
    }
    if(sum<n) cout<<-1<<endl;
    else {
        ll ans=0,tmp=0;
        for(ll i=0;i<=58;i++)
        {
            if((n>>i)&1) {
                ll c=0;
                for(ll j=0;j<=i;j++) c+=p[j]*(1<<j);
                if(c-tmp>=(1<<i)) tmp+=(1<<i);
                else {
                    ll poll=-1;
                    for(ll j=i+1;j<=58;j++){
                        if(p[j]){
                            poll=j;
                            break;
                        }
                    }
                    ans+=poll-i;
                    p[poll]--;
                    for(ll k=poll-1;k>=i;k--) p[k]++;
                }
            }
        }
        cout<<ans<<endl;
    }
}
int main(){
    ll t;
    cin>>t;
    while(t--) solve();
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/12336165.html