\[\texttt{Preface}
\]

不开 long long 见祖宗。

\[\texttt{Description}
\]

你有一个 \(n\) 码的袋子,你还有 \(m\) 个盒子,第 \(i\) 个盒子的尺寸是 \(a_i\) ,这里的每一个 \(a_i\) 都是 \(2\) 的非负幂整数。

你可以把盒子分成大小相等的两部分。你的目标是完全装满袋子。

例如 \(n=10,a=[1,1,32]\) ,那么你必须把 \(32\) 码的盒子分成 \(16\) 码的两部分,然后把 \(16\) 码的盒子分开,你可以用 \(1\) 码,\(1\) 码,\(8\) 码的盒子装满袋子。

计算填充尺寸为 \(n\) 的袋子所需的最小分割数。

**多组数据,无解输出 -1 。 **

\[\texttt{Solution}
\]

先来讨论一下 -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}\) 。

\[\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;
}

\[\texttt{Thanks} \ \texttt{for} \ \texttt{watching}
\]

题解【CF1303D Fill The Bag】的更多相关文章

  1. [CF1303D] Fill The Bag - 贪心

    Solution 考虑从低位往高位贪心,设当前在处理第 \(i\) 位,更低位剩余的部分一共可以拼出 \(cnt\) 个 \(2^i\) 如果 \(n\) 的这一位是 \(1\) ,那么这一位就需要处 ...

  2. I - Fill The Bag codeforces 1303D

    题解:注意这里的数组a中的元素,全部都是2的整数幂.然后有二进制可以拼成任意数.只要一堆2的整数幂的和大于x,x也是2的整数幂,那么那一堆2的整数幂一定可以组成x. 思路:位运算,对每一位,如果该位置 ...

  3. Codeforces1303D. Fill The Bag

    1e18对应2进制有58位,可以直接暴力模拟,因为读入的数都是2次幂,__builtin_ctz这个内置gcc函数可以算出二进制下末尾有几个0,读入时统计,然后从n的最低位开始判断,注意每次升位的时候 ...

  4. 2021record

    2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...

  5. 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 ...

  6. 【题解】Educational Codeforces Round 82

    比较菜只有 A ~ E A.Erasing Zeroes 题目描述: 原题面 题目分析: 使得所有的 \(1\) 连续也就是所有的 \(1\) 中间的 \(0\) 全部去掉,也就是可以理解为第一个 \ ...

  7. codeforces 148E Aragorn's Story 背包DP

    Aragorn's Story Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/probl ...

  8. [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 ...

  9. Codeforces题解集 1.0

    记录 Codeforces 2019年12月19日到 2020年2月12日 的部分比赛题 Educational Codeforces Round 82 (Rated for Div. 2) D Fi ...

随机推荐

  1. ArcEngine 创建要素,删除要素,生成网格,渲染图层(VB)

    示例代码:https://github.com/yu969890202/ArcEngine/tree/master/WinFrom_ArcEngine_PointDistribution博客后面有两张 ...

  2. vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多

    一.思路分析和效果图 用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果.然后针对这几个效果的实现,捋下思路: 根据加载数据的顺序,依次追加标签展示效果: 选择哪种方式实 ...

  3. 正则表达式grep命令

    grep命令 作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查:打印匹配到的行. 模式::由正则表达式字符及文本字符所编写的过滤条件 语法:grep [OPTIONS] PATTE ...

  4. TensorFlow——tensorflow编程基础

    0.tensorflow中的模型运行基础 tensorflow的运行机制属于定义和运行相分离,在操作层面可以抽象成两种:模型构建和模型运行. 在模型构建中的常见概念: 张量(tensor):数据,即某 ...

  5. Ubuntu TTY 字体大小 目录颜色 中文乱码 设置

    TTY有很多不舒服的地方,没有中文 目录是深蓝色的看不清楚 字太小. 通过设置让终端更舒服一些. 进入TTY 从桌面进入TTY: 按`Ctrl+Alt+F[1-9] 有的版本图形界面在F7和F8,有的 ...

  6. dp - 递推

    C. Multiplicity time limit per test 3 seconds memory limit per test 256 megabytes input standard inp ...

  7. 数字任意组合 - gcd

    链接:https://www.nowcoder.com/acm/contest/160/A来源:牛客网 题目描述有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an ...

  8. 读取配置文件,appsettings.json和注入ICO

    https://www.cnblogs.com/knowledgesea/p/7079880.html 引入Nuget的两个类库 Microsoft.Extensions.Configuration ...

  9. scala基本语法

    scala基本语法scala函数1 def定义方法2 方法的返回值类型可以省略3 方法体重最后一行计算结果可以返回 return 如果省略方法类型4 方法参数 要指定类型5 如果方法体可以一步搞定 方 ...

  10. 如何选择kmeans中的k值——肘部法则–Elbow Method和轮廓系数–Silhouette Coefficient

    肘部法则–Elbow Method 我们知道k-means是以最小化样本与质点平方误差作为目标函数,将每个簇的质点与簇内样本点的平方距离误差和称为畸变程度(distortions),那么,对于一个簇, ...