Educational Codeforces Round 82 (Rated for Div. 2) D. Fill The Bag

与世无争的帅哥 提交于 2020-02-18 03:22:47

题目链接
大意:给你一些2的幂次数,问你最少分解几次可以用一些2的幂次数得到n。
分解指的是:2x>22x1x02^x->2*2^{x-1},x\geq0
思路:把n按二进制拆分,从小到大枚举每一位1:先看低位能不能凑齐,否则从高位拆。
细节见代码:(写的比较复杂,理解是很好理解的)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int t;
LL n;
int m, a[N];
LL res[88];
int fine(int x, LL num) {
  if (!num)
    return 1;
  if (x < 0)
    return 0;
  if (res[x] >= num) {
    return 1;
  }
  if (res[x] < num) {
    return fine(x - 1, (num - res[x]) << 1);
  }
}
void dele(int x, LL num) {
  if (x < 0 || !num)
    return;
  if (res[x] >= num) {
    res[x] -= num;
    return;
  }
  dele(x - 1, (num - res[x]) << 1);
  res[x] = 0;
  return;
}
int ga(int x) {
  int l = x;
  for (; x <= 60; x++) {
    if (res[x]) {
      res[x]--;
      for (int j = x - 1; j >= l; j--) {
        res[j]++;
      }
      return x - l;
    }
  }
  return -1;
}
int main() {
  ios::sync_with_stdio(false);
  for (cin >> t; t; t--) {
    cin >> n >> m;
    LL tot = 0;
    memset(res, 0, sizeof res);
    auto get = [&](int x) {
      int cn = 0;
      while (x) {
        ++cn;
        x /= 2;
      }
      return cn - 1;
    };
    for (int i = 1; i <= m; i++) {
      cin >> a[i], tot += a[i];
      int x = get(a[i]);
      res[x]++;
    }
    if (tot < n)
      cout << -1 << '\n';
    else if (tot == n)
      cout << 0 << '\n';
    else {
      int sta = 0, tm = 0;
      LL dis = n;
      for (int j = 0; j <= 60; j++) {
        if (dis & (1ll << j)) {
          if (fine(j, 1)) {
            dele(j, 1);
          } else {
            int x = ga(j);
            if (x == -1) {
              sta = 1;
              break;
            } else {
              tm += x;
            }
          }
        }
      }
      if (sta) {
        cout << -1 << '\n';
      } else {
        cout << tm << '\n';
      }
    }
  }
  return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!