标签:targe long lld printf highlight $1 scanf codeforce 大小
网址:https://codeforces.com/contest/1303/problem/D
给出空间为$n$的容器和$m$个盒子。这些盒子的大小都是$2^k$的正整数,且可以减半,问使得容器刚好被盒子装满的最小减半次数是多少,如果不可能刚好装满,输出$-1$。
统计$2^k$大小的盒子有多少个,然后从低位到高位贪心,因为高位的一定需要减半才能到低位,所以就会增加减半次数,而低位变成高位却无影响。对于某一位$i$,如果它是$1$,那么对于这一位,如果已经没有了大小是$2^i$的盒子,则需要从$i+1$位的减半一次,$i+1$位上的盒子数是$-1$也没有关系,因为它会从$(i+1)+1$位拿过来,类似于减法退位。如果有剩下的,就直接合并到$i+1$位,最后输出减半次数就是答案。
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int cnt[65]; int solve() { memset(cnt, 0, sizeof(cnt)); ll n, sum = 0; int m, a; scanf("%lld%d", &n, &m); for (int i = 1; i <= m; ++i) { scanf("%d", &a); sum += a; int tmp = 0; while (a > 1) ++tmp, a >>= 1; ++cnt[tmp]; } if (sum < n) return printf("-1\n"), 0; int ans = 0; for (int i = 0; i <= 63; ++i) { int x = (n >> i) & 1; cnt[i] -= x; if (cnt[i] >= 2) cnt[i + 1] += cnt[i] / 2, cnt[i] -= (cnt[i] / 2) * 2; if (cnt[i] < 0) --cnt[i + 1], ++ans; } return printf("%d\n", ans), 0; } int main() { int t; scanf("%d", &t); while (t--) solve(); return 0; }
codeforces1303D Fill The Bag 二进制应用and贪心
标签:targe long lld printf highlight $1 scanf codeforce 大小
原文地址:https://www.cnblogs.com/Aya-Uchida/p/12319619.html