题解倒水

Posted 2021-yanghaoran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解倒水相关的知识,希望对你有一定的参考价值。

题目描述

一天,树树买了N个容量可以认为是无限大的瓶子,初始时每个瓶子里有1升水。树树发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子合并,把一个瓶子里的水全部倒进另一个瓶子,然后把空瓶丢弃(不能丢弃有水的瓶子)。
显然在某些情况下树树无法达到目标,比如N=3,K=1。此时树树会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以达到目标。
现在树树想知道,最少需要买多少新瓶子才能达到目标呢?

输入输出格式

输入格式:

一行,两个正整数N,K(1≤N≤(10^9),K≤1000)。

输出格式:

一个非负整数,表示最少需要买多少新瓶子。

输入输出样例

输入样例一:

3 1

输出样例一:

1

输入样例二:

13 2

输出样例二:

3

输入样例三:

1000000 5

输出样例三:

15808

说明

样例说明:

考虑lowbit运算。所谓lowbit运算,就是把n的二进制的高位1全部清空,只留下最低位的1,比如10的二进制是1010,则lowbit(n)=lowbit(1010)=0010(二进制)。

数据规模:

对于30%的数据,N≤3×(10^5)
对于50%的数据,n≤(10^7)
对于100%的数据,如题目所述。

因为题目提示了lowbit运算,所以就是要用位运算
而做位运算的基本思路就是
通过特殊到一般,找出规律
我们来推算一下样例
输入:

3 1

推算:

1 1 1
2 1

把能合并的全部合并后,发现剩下2个,然后把(3)10转换为二进制得到(11)2
也就是说,合并之后所剩下的瓶子个数,就是原数n的二进制中1的个数
那么,到底要买多少个瓶子呢?
题目提示我们考虑lowbit运算

(3)10=(11)2
3+lowbit(3)=(11)2+(1)2=(100)2

也就是说,每加上一个lowbit(n),就会把最低位的1往高位移动,然后就能合并,消除
就是当剩下瓶子数大于K时,就往n中加lowbit(n)
AC代码:

#include<iostream>
using namespace std;
int n,k;
int lowbit(int n)
{
	return n&(-n);
}
int cnt(int n)
{
	int res;
	while(n!=0)
	{
		res+=n%2;
		n/=2;
	}
	return res;
}
int main()
{
	cin>>n>>k;
	int ans=0;
	while(cnt(n)>k)
	{
		ans+=lowbit(n);
		n+=lowbit(n);
	}
	cout<<ans;
}

注意

lowbit(n)=n&(-n)
有可能要用long long

以上是关于题解倒水的主要内容,如果未能解决你的问题,请参考以下文章

题解Luogu P1582 倒水 二进制

1226 倒水问题

USACO Mother&#39;s Milk(bfs)

POJ 3585 Accumulation Degree 题解

Problem E: 倒水(Water)

UVA10603Fill题解--BFS