原题链接:
Problem E: 倒水(Water)
Description
一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)
显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。
现在CC想知道,最少需要买多少新瓶子才能达到目标呢?
Input
第一行一个整数T,表示有T组数据。
接着T行,每行两个正整数, N,K(1<=N<=10^9,K<=1000)。
Output
Sample Input
Sample Output
*********************************************************************************************** 题意:
有n个瓶子,每个瓶子里有1升的水,当两个瓶子的水一样的时候,可以把2个瓶子合到一起,给了个k,还要加多少个瓶子才能够使总的瓶子合成不超过k个瓶子。
题解:
1) 我一开始想这一题毫无疑问是贪心,当出现奇数瓶子的时候就补上当前瓶子里的水(因为瓶子里的水就是n个1升水的个数)。然后发现第3个sample不对,算多了。
然后就突然想到,当出现奇数个瓶子的时候,把那一个瓶子拿到一边去(记录起来),剩下的两两合并。画了一下相对一种ans有减少。但是第3个样例不对。
最后发现我一开始把瓶子压到小于k的时候就停止了。其实还可以继续往下压缩,直到要缩到最后一个。(现在只有一个瓶子了)
在从记录起来的瓶子里从大到小补全k-1个瓶子(有k-1个瓶子了),把记录里面剩下的瓶子通过补充瓶子最后合并成一个瓶子。
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include
题解一
2)官方题解:
看了一下题解,发现题解十分的巧妙。灵活运用 x&(-x) 和 n&=(n-1) ;
简单讲一下 x&(-x)是求 x 2进制时最低位的1的2^k的值,而n&=(n-1)是用来求 n 里有多少个1。
1 int cnt(int n){ //计算n中有多少个12 int num=0;3 while(n>0){4 num++;5 n&=(n-1);6 }7 return num;8 }
求有多少个1
贴上具体代码
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include
题解二
果然我还是太菜了XD。