P1582 倒水(C++_数论_进制)

题目描述

一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)

显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。

现在CC想知道,最少需要买多少新瓶子才能达到目标呢?

输入格式

一行两个正整数, N,K( 1 N 2 × 1 0 9 , K 1000 1\le N\le 2\times 10^9,K\le 1000 )。

输出格式

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

输入输出样例

输入 #1

3 1

输出 #1

1

输入 #2

13 2

输出 #2

3

输入 #3

1000000 5

输出 #3

15808

思路

这就是这个题和进制之间的关系:(具体思路看代码注释!)

合并前 二进制 合并后
1个瓶子 1 1个瓶子
2个瓶子 10 1个瓶子
3个瓶子 11 2个瓶子
4个瓶子 100 1个瓶子
5个瓶子 101 2个瓶子
6个瓶子 110 2个瓶子
7个瓶子 111 3个瓶子
8个瓶子 1000 1个瓶子

源码

#include<bits/stdc++.h>
using namespace std;

int judge(int p)//计算二进制中1的个数
{
	int num = 0;
	while (p>0)//强行套用快速幂模板
	{
		if (p & 1)
			num++;
		p >>= 1;
	}
	return num;
}
int main()
{
	int n, k, ans = 0;
	cin >> n >> k;
	while (judge(n) > k)//最后可以合并成的杯子数量大于要求的杯子数量(不符合要求)
	{
		ans += n & -n;//n&-n是n的二进制从右往左数第一个1所在的位置代表的权值i^n,ans加上这个值是因为下面一步n += n & -n;进位(要么1变少,要么1数量不变)
		n += n & -n;
	}
	cout << ans;
	return 0;
}
发布了228 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43510916/article/details/104238250