推了一个多小时的式子,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);
}

P1582倒水的更多相关文章

  1. 洛谷 P1582 倒水 解题报告

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  2. P1582 倒水 (数学)

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  3. 洛谷P1582 倒水

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  4. 洛谷P1582 倒水 二进制 lowbit __builtin_popcount

    P1582 倒水:https://www.luogu.org/problemnew/show/P1582 题意: 给定n瓶装有1升的水瓶,每次可以把两瓶装水量相同的水和成一瓶,问最少还要增加几瓶装有1 ...

  5. 洛谷 - P1582 - 倒水 - 位运算

    https://www.luogu.org/problemnew/show/P1582 要求用最少的瓶子,那肯定不能有两个一样的瓶子,否则合并更优. 枚举其二进制位,每次加上lowbit,将最后一个1 ...

  6. 洛谷P1582 倒水 二进制的相关应用

    https://www.luogu.org/problem/P1582 #include<bits/stdc++.h> using namespace std; long long N,K ...

  7. P1582 倒水(贪心 + lowbbit)

    https://www.luogu.com.cn/problem/P1582 #include <bits/stdc++.h> using namespace std; #define i ...

  8. P1582 倒水

    传送门 思路: 类似于 袁绍的刁难 , 一道二进制的模拟题. 先将:将原先的瓶子数 n 转换成二进制,二进制中 1 的个数就是合并后剩下的瓶子个数 . 主要利用树状数组的 lowbit 函数: inl ...

  9. 洛谷P1582 倒水题解

    题目 分析 这个题并不难,只是需要仔细思考我们首先可以很轻松的把这个题给疏通一下题意. 1:首先我们最后每个瓶子中装的水一定是一个$2^x$,因为每次都是$2$倍的加,这个应该很好理解. 2:我们要明 ...

随机推荐

  1. win

    /*-------------------------------------------------------------- HelloMsg.c -- Displays "Hello, ...

  2. Java多态性应用——多态数组、多态参数

    多态数组: Person[] person = {new Person("张三", 32), new Student("李四", 21, 120, 90.0), ...

  3. [BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap)

    [BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap) 题面 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数 ...

  4. Ubuntu 中查找软件安装的位置

    Ubuntu 中查找软件安装的位置 执行该程序 直接执行该程序,有时候一些程序执行时会显示出自己的位置,比如: 用命令 ps -e 找到该程序的名字 用 find 或 whereis 命令查找文件位置 ...

  5. wxpython中单选框的两种创建方式源码展示

    #coding=utf-8 import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1, ...

  6. NGUI的HUD Text的扩展插件学习--(UIFollowTarget)的使用

    一,我们先导入NGUI_HUD_Text_v1.11包,导入包后会在项目生成一个这样的文件夹 二,我们添加一个cube,给cube添加一个空的游戏对象 二,我们使添加一个label,然后给label添 ...

  7. git Windows终端安装教程

    1.下载网址:https://gitforwindows.org/ 2.双击压缩包出现: 3.点击下一步后,选择安装路径: 根据自己的需求选择路径 4.选择安装的组件,建议全选 [每一条解析:] Ad ...

  8. vue路由守卫配合权限,白名单

    router.beforeEach(async(to, from, next) => { // 进度条开始 NProgress.start() // 确认用户是否已登录(获取它的token值,这 ...

  9. [CQOI2015]网络吞吐量(网络流+SPFA)

    [CQOI2015]网络吞吐量 题目描述 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的 ...

  10. Linux shell中自动完成登录

    在写shell脚本时,需要登录到不同的服务器上执行相关命令,在未建立信任之前如何批量操作. 1.ssh 首次登录服务器时会提示RSA key fingerprint输入yes/no,可以通过下面的方法 ...