题解【CF1303D Fill The Bag】
\]
不开 long long 见祖宗。
\]
你有一个 \(n\) 码的袋子,你还有 \(m\) 个盒子,第 \(i\) 个盒子的尺寸是 \(a_i\) ,这里的每一个 \(a_i\) 都是 \(2\) 的非负幂整数。
你可以把盒子分成大小相等的两部分。你的目标是完全装满袋子。
例如 \(n=10,a=[1,1,32]\) ,那么你必须把 \(32\) 码的盒子分成 \(16\) 码的两部分,然后把 \(16\) 码的盒子分开,你可以用 \(1\) 码,\(1\) 码,\(8\) 码的盒子装满袋子。
计算填充尺寸为 \(n\) 的袋子所需的最小分割数。
**多组数据,无解输出 -1
。 **
\]
先来讨论一下 -1
的情况:
考虑到分裂一个数不会影响到所有数的和。
那么我们将所有数都分裂成 \(1\) ,由于和不变,此时 \(1\) 的个数为 \(\sum\limits_{i=1}\limits^{m}a[i]\) ,也就是说小于等于 \(\sum\limits_{i=1}\limits^{m}a[i]\) 的数都可以被填出来。
故当 \(n>\sum\limits_{i=1}\limits^{m}a[i]\) 时,无解。
\(~\)
有一个看起来很正确的贪心策略:
将 \(n\) 二进制拆分成 \(2^{k_1},2^{k_2},...,2^{k_c}\) 。
然后从低位(\(2^{k_1}\))到高位(\(2^{k_c}\))贪心填数。
假设我们当前处理到的数为 \(2^{k_i}\) 。
首先考虑位数小于等于 \(k_i\) 的所有数中,能不能凑成 \(2^{k_i}\) ,若可以,直接填上去;否则考虑分裂位数大于 \(k_i\) 的所有数中最小的那一个,使其经过若干次分裂,分裂成 \(2^{k_i}\) 。
详情见 \(\texttt{Code}\) 。
\]
#include<cstdio>
#include<cstring>
#define RI register int
using namespace std;
const int N=100100;
int T;
long long n; int m;
int a[N];
long long ans,sum;
long long cnt[65]; // cnt[k] : 2^k 的出现次数
long long calc(int k) // 计算小于等于 k 的位数中可以组成多少个 2^k
{
long long ans=0;
for(RI i=0;i<k;i++)
ans=(ans+cnt[i])/2;
return ans+cnt[k];
}
void work()
{
memset(cnt,0,sizeof(cnt));
ans=sum=0;
scanf("%lld%d",&n,&m);
for(RI i=1;i<=m;i++)
scanf("%d",&a[i]),sum+=a[i];
if(n>sum)
{
puts("-1");
return;
}
for(RI i=1;i<=m;i++)
for(RI j=0;j<=31;j++)
if((a[i]>>j)&1)
{
cnt[j]++;
break;
}
for(RI k=0;k<=63;k++)
{
if(((n>>k)&1)==0)continue; // 如果 n 的第 k 位为 0 就 continue
if(calc(k)) // 情况 1
cnt[k]--; // 理论上应该要让组成 2^k 的那些数减 , 但实际上这样做 , 在 calc 里也是正确的
else // 情况 2
{
for(RI p=k+1;p<=63;p++) // 找到位数大于 k 的数中最小的那个
if(cnt[p])
{
cnt[p]--; // 模拟分裂
for(RI i=k;i<p;i++)
cnt[i]++; // 模拟分裂
ans+=p-k; // 统计答案
break;
}
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&T);
while(T--) work();
return 0;
}
\]
题解【CF1303D Fill The Bag】的更多相关文章
- [CF1303D] Fill The Bag - 贪心
Solution 考虑从低位往高位贪心,设当前在处理第 \(i\) 位,更低位剩余的部分一共可以拼出 \(cnt\) 个 \(2^i\) 如果 \(n\) 的这一位是 \(1\) ,那么这一位就需要处 ...
- I - Fill The Bag codeforces 1303D
题解:注意这里的数组a中的元素,全部都是2的整数幂.然后有二进制可以拼成任意数.只要一堆2的整数幂的和大于x,x也是2的整数幂,那么那一堆2的整数幂一定可以组成x. 思路:位运算,对每一位,如果该位置 ...
- Codeforces1303D. Fill The Bag
1e18对应2进制有58位,可以直接暴力模拟,因为读入的数都是2次幂,__builtin_ctz这个内置gcc函数可以算出二进制下末尾有几个0,读入时统计,然后从n的最低位开始判断,注意每次升位的时候 ...
- 2021record
2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...
- Educational Codeforces Round 82 (Rated for Div. 2) A-E代码(暂无记录题解)
A. Erasing Zeroes (模拟) #include<bits/stdc++.h> using namespace std; typedef long long ll; ; in ...
- 【题解】Educational Codeforces Round 82
比较菜只有 A ~ E A.Erasing Zeroes 题目描述: 原题面 题目分析: 使得所有的 \(1\) 连续也就是所有的 \(1\) 中间的 \(0\) 全部去掉,也就是可以理解为第一个 \ ...
- codeforces 148E Aragorn's Story 背包DP
Aragorn's Story Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/probl ...
- [CF百场计划]#3 Educational Codeforces Round 82 (Rated for Div. 2)
A. Erasing Zeroes Description You are given a string \(s\). Each character is either 0 or 1. You wan ...
- Codeforces题解集 1.0
记录 Codeforces 2019年12月19日到 2020年2月12日 的部分比赛题 Educational Codeforces Round 82 (Rated for Div. 2) D Fi ...
随机推荐
- 投票:OAuth2.0 技术选型你会怎么选
1. 前言 在使用 OAuth2.0 中 Authorization Server (授权服务器)是一个回避不了的设施,在大多数情况下我们调用的是一些知名的.可靠的.可信任的第三方平台,比如 QQ.微 ...
- 【转】Java 正则表达式详解
正则表达式30分钟入门教程 常用正则表达式 如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单. 如果你不熟悉这个术语,那么“正则表达式”(R ...
- spring-boot内嵌三大容器https设置
spring-boot内嵌三大容器https设置 spring-boot默认的内嵌容器为tomcat,除了tomcat之前还可以设置jetty和undertow. 1.设置https spring-b ...
- php进程 热更新
后台启动的php守护进程时 文件内include的代码变更并未生效,需要重启进程,我们可以更新代码后手动重启.但是有些对失效要求较高.那就需要自动重启了.下面整理出三个方案用以实现. 1 inoti ...
- Java final关键词
final关键词的四种用法 * * final 关键字:最终的.不可改变的 * 1.可以用来修饰一个类 * 2.可以用来修饰一个方法 * 3.可以用来修饰一个局部变量 * 4.可以用来修饰一个成员变量 ...
- 【xinsir】webpack实践
webpack现在是前端必会的技能了,也是在工作中必定用到的.所以,如果我们现在还不会webpack,那么在将来面试中肯定会被扣分的. webpack中文官网:https://www.webpackj ...
- cogs 728. [网络流24题] 最小路径覆盖问题 匈牙利算法
728. [网络流24题] 最小路径覆盖问题 ★★★☆ 输入文件:path3.in 输出文件:path3.out 评测插件时间限制:1 s 内存限制:128 MB 算法实现题8-3 最 ...
- SQLiteOpenHelperde的oncreate方法
main中
- pycharm 安装vue
1.设置JS为ES6 2.安装vue.js 3.重启pycharm 4.检查
- [bzoj1875] [洛谷P2151] [SDOI2009] HH去散步
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...