倒水

【题目描述】
一天,树树买了 N 个容量可以认为是无限大的瓶子,初始时每个瓶子里有 1 升水。
树树发现瓶子实在太多了,于是他决定 保留不超过 K 个瓶子。每次他选择两个当前含
水量相同的瓶子合并,把一个瓶子的水全部倒进另一个瓶,然后把空瓶丢弃(不能丢
弃有水的瓶子)。
显然在某些情况下树树无法达到目标,比如 N=3,K=1.此时树树会重新买一些新
的瓶子(新瓶子容量无限,开始时有 1 升水),以达到目标。
现在树树想知道,最少需要买多少新瓶子才能达到目标呢?
【输入文件】
一行两个正整数 N,K(1<=N<=10 9 ,K<=1000)。
【输出文件】
一个非负整数,表示最少需要买多少新瓶子。
【样例输入】
3 1
【样例输出】
1
【数据规模】
对于 30%的数据,N<=3*10 5
对于 100%的数据如题目。

把能合并的合并,发现剩下的瓶子是n二进制数中1的个数

如果大于k,那么就要从小位消除

消除方法就是给原数不断加上lowbit(n)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 long long n,k,ans;
 8 long long count(long long x)
 9 {
10   int cnt=0;
11   while (x)
12     {
13       x-=(x&(-x));
14       cnt++;
15     }
16   return cnt;
17 }
18 int main()
19 {
20   cin>>n>>k;
21   ans=0;
22   while (count(n)>k)
23     {
24       ans+=(n&(-n));
25       n+=(n&(-n));
26     }
27   cout<<ans;
28 }

 

posted @ 2017-11-02 21:34  Z-Y-Y-S  阅读(363)  评论(0编辑  收藏  举报