推了一个多小时的式子,ac后一看题解,7行代码搞定

emmmm我还是太菜了

传送

蒟蒻解法:

不管怎么倒水,最终所有瓶子里面的水的数量一定可以用2k表示出来。

n最终可以合并成几个瓶子呢?

我们可以把n分解为多个2k相加的形式,例如:13=23+22+20,所以13最少合并到3个瓶子里面

求n最少能合并到几个瓶子里面,正是看n的二进制表示里面有多少个1

如果1的数量cnt小于等于k,则直接输出0。

否则:从第一个是1的位置+1开始,扫到cnt-k+1个1的位置,中间如果是0,ans就加上2是0的位置,最后ans+2第一个是1的位置

粗略的解释一下

假设某个数的二进制表示是1000101001000,k=2

加上23:1000101010000

加上24:1000101100000

加上25:1000110000000

加上27:1001000000000

对比刚开始的n:100101001000

标0的是加完后最后一个1所在的位置。

我们发现在原始的n的第一个1开始,一直到cnt-k+1的1的位置,中间是0的地方都要在答案上加2k(当然第一个是1的地方除外)

maybe代码会好懂一些

#include<bits/stdc++.h>
using namespace std;
int n,a[],b[],cnt,k,now,ans;//a[i]记录n的二进制表示中,2^i所对应的位上是0还是1,b[i]记录第i个1的位置
long long mi[];//mi[i]为2^i
int read()
{
char ch=getchar();
int x=; bool f=;
while(ch<''||ch>'')
{
if(ch=='-')
f=;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return f?-x:x;
}
void init()
{
mi[]=;
for(int i=;;i++)
{
mi[i]=mi[i-]*;
if(mi[i]>n)break;//mi不开long long见祖宗
}
}
int main()
{
n=read();k=read();
init();
while(n)
{
a[now]=n&;//now代表当前是2^now所代表的位置
if(n&)
{
b[++cnt]=now;
}
now++;
n>>=;
}
if(cnt<=k)//特判
{
printf("");return ;
}
int m=cnt-k+;
ans+=mi[b[]];
for(int i=b[]+;i<=b[m];i++)
{
if(a[i]==)ans+=mi[i];
}
printf("%d\n",ans);
}

大佬做法:

因为所有的水都是由两份相同的水合并而成的,因此每瓶水的体积一定是2^i,(i\in N)2i,(i∈N)升。

最后保留k个瓶子,那么最后总的升数的二进制表示中,1的个数一定<=k。

那么我们只要贪心地往n上加上lowbit(n)即可。

这个lowbit就是树状数组那个lowbit啦

简化代码的trick:

使用内置函数\_\_builtin\_popcount()来计算一个数的二进制表示中1的数量。

这样下来,代码简化到仅剩7行。

惊不惊喜,意不意外?

------------------------摘自洛谷第一篇题解

#include <cstdio>
int n, k, ans;
int main() {
scanf("%d%d", &n, &k);
while(__builtin_popcount(n) > k) ans += n & -n, n += n & -n;
printf("%d", ans);
}

最新文章

  1. hdu 2222 Keywords Search
  2. 数据结构(DataStructure)与算法(Algorithm)、STL应用
  3. Java之MS SQL数据库连接
  4. PAT-乙级-1026. 程序运行时间(15)
  5. DOM五大对象
  6. 调用[[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPad判断设备
  7. c#超时锁定
  8. 重复弹Toast的解决方案
  9. 201521123081《java程序设计》 第7周学习总结
  10. JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)
  11. 总结Oracle8i 的UNDO表空间损坏(ORA-01092及ORA-00600【4193】)情况下的数据库不完全恢复的经历
  12. SpringCloud的应用发布(四)顺序启动各个应用
  13. 集群IPtables转发与防火墙
  14. log4j 配置,tomcat 启动或有后台操作时,控制台会显示很多 DEBUG 信息
  15. (POJ-3279)Fliptile (dfs经典---也可以枚举)
  16. c#用EPPLUS操作excel
  17. gdb初步窥探
  18. Useful JVM Flags – Part 8 (GC Logging)
  19. mysqldump工具,工作的本质是什么呢?(dump表的时候,是否会产生drop表的语句)
  20. 阅读笔记:Solving the “false positives” problem in fraud prediction

热门文章

  1. DevOps的前世今生
  2. HashMap对象转换为JavaBean对象
  3. git常用相关操作
  4. frontend-dev面试
  5. open, creat - 用来 打开和创建 一个 文件或设备
  6. 在数据库中分析sql执行性能
  7. Linux学习之旅(一)Linux常用命令
  8. git路径超长 及gitignore
  9. highlight语法高亮推荐样式
  10. alert(1) to win