2017广东工业大学程序设计竞赛 E倒水(Water)

原题链接:http://www.gdutcode.sinaapp.com/problem.php?cid=1057&pid=4

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

3 3 1 13 2 1000000 5

Sample Output

1 3 15808

***********************************************************************************************

题意:

  有n个瓶子,每个瓶子里有1升的水,当两个瓶子的水一样的时候,可以把2个瓶子合到一起,给了个k,还要加多少个瓶子才能够使总的瓶子合成不超过k个瓶子。

题解:

  1) 我一开始想这一题毫无疑问是贪心,当出现奇数瓶子的时候就补上当前瓶子里的水(因为瓶子里的水就是n个1升水的个数)。然后发现第3个sample不对,算多了。

    然后就突然想到,当出现奇数个瓶子的时候,把那一个瓶子拿到一边去(记录起来),剩下的两两合并。画了一下相对一种ans有减少。但是第3个样例不对。

    最后发现我一开始把瓶子压到小于k的时候就停止了。其实还可以继续往下压缩,直到要缩到最后一个。(现在只有一个瓶子了)

    在从记录起来的瓶子里从大到小补全k-1个瓶子(有k-1个瓶子了),把记录里面剩下的瓶子通过补充瓶子最后合并成一个瓶子。

    

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define mset(a, b)  memset((a), (b), sizeof(a))
16 typedef long long LL;
17 const int inf = 0x3f3f3f3f;
18 const int maxn = 1000+10;
19 vector <int > hehe;
20 int solve(int n, int water)
21 {
22     if(n==1)    return water;
23     if(n%2==0){
24         solve(n/2, water*2);
25     }
26     else{
27         hehe.pb(water);
28         solve((n-1)/2, water*2);
29     }
30 }
31 int main()
32 {
33     int T;
34     cin >> T;
35     while(T--)
36     {
37         int N, K;
38         cin >> N >> K;
39         if(N<=K)
40             cout << "0" << endl;
41         else
42         {
43             int endnum=solve(N, 1);
44             if(hehe.empty()){
45                 cout << "0" << endl;
46             }
47             else{
48                 int ans =0;
49                 if(K==1){
50                     ans = endnum;
51                     for(int i=0;i<hehe.size();i++)  ans -= hehe[i];
52                 }
53                 else
54                 {
55 //                    for(int i =0 ;i< hehe.size();i++)   cout <<hehe[i] <<endl;
56                     int need = K -1;
57                     if(need == 1){
58                         ans = hehe[hehe.size()-1];
59                         for(int i=0;i<hehe.size()-1;i++)    ans -=hehe[i];
60                     }
61                     else{
62                         ans = hehe[hehe.size() - need];
63                         for(int i=0;i<hehe.size()-need;i++) ans-=hehe[i];
64                     }
65                 }
66                 cout <<ans << endl;
67             }
68         }
69         hehe.clear();
70     }
71     return 0;
72 }

题解一

  2)官方题解:

    

    看了一下题解,发现题解十分的巧妙。灵活运用 x&(-x) 和 n&=(n-1) ;

    简单讲一下 x&(-x)是求 x 2进制时最低位的1的2^k的值,而n&=(n-1)是用来求 n 里有多少个1。

1 int cnt(int n){//计算n中有多少个1
2     int num=0;
3     while(n>0){
4         num++;
5         n&=(n-1);
6     }
7     return num;
8 }

求有多少个1

    贴上具体代码

    

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <vector>
 7 #include <map>
 8 #include <set>
 9 #include <queue>
10 #include <sstream>
11 #include <algorithm>
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define ms(a, b)  memset((a), (b), sizeof(a))
16 //#define LOCAL
17 typedef long long LL;
18 const int inf = 0x3f3f3f3f;
19 const int maxn = 10000+10;
20 const int mod = 1e9+7;
21 int cnt(int n){//计算n中有多少个1
22     int num=0;
23     while(n>0){
24         num++;
25         n&=(n-1);
26     }
27     return num;
28 }
29 int lowbit(int x){
30     return x&(-x);
31 }
32 int main()
33 {
34     #ifdef LOCAL
35         freopen("input.txt" , "r", stdin);
36     #endif // LOCAL
37     int T, n, k;
38     cin >> T;
39     while(T--){
40         cin >> n >> k;
41         int ans =0;
42         while(cnt(n)>k){
43             ans += lowbit(n);
44             n+=lowbit(n);//补上lowbit(n)个瓶子,就会进位。
45         }
46         cout << ans << endl;
47     }
48     return 0;
49 }

题解二

果然我还是太菜了XD。

   

时间: 2024-10-25 04:10:14

2017广东工业大学程序设计竞赛 E倒水(Water)的相关文章

2017广东工业大学程序设计竞赛决赛-tmk买礼物

tmk买礼物 Description 今天是校赛的日子,为了庆祝这么喜庆的日子,TMK打算买些礼物给女票LSH庆祝一下. TMK进入了雪梨超市,然后刚踏入的一瞬间,店主就对TMK说:“恭喜你成为了本店第2147483647位顾客,本店在搞一个活动,对本店第2147483647位顾客进行赠送活动.你先看看你有多少钱?” TMK一摸口袋,发现只有n个硬币,每个硬币的价值为a[i]. 然后店主继续说:“现在你用你的钱凑一些数,如果你的钱能凑成[0,x]里面所有的数,那么你将会免费获得该店价值x元的代金

2017广东工业大学程序设计竞赛决赛 G 等凹数字

题意: Description 定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字.现在问你[L,R]中有多少等凹数字呢? Input 第一行一个整数T,表示数据的组数. 接下来T行每行俩个数字L和R,(1<=L<=R<=1e18) Output 输出一个整数,

华南师大 2017 年 ACM 程序设计竞赛新生初赛题解

华南师大 2017 年 ACM 程序设计竞赛新生初赛题解 华南师范大学第很多届 ACM 程序设计竞赛新生赛(初赛)在 2017 年 11 月 20 日 - 27 日成功举行,共有 146 名同学有效参赛(做出 1 题).进入决赛的资格初定为完成并通过 5 题或以上,决赛时间是 12 月 3 日,地点未定. 题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff 思维

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为  n 的简单多边形,每次只能画一条边或者一个格子的对角线,问至少要画几条. 解法:如果一个斜着的矩形长宽分别是 a,b,那么它的面积是 2ab.最优解肯定是离 sqrt(n/2)很近的位置.想想 n=5 时答案为什么是7 然后在那个小范围内枚举一下就好了.我给一张做题时画的图 #include <bits/stdc++.h> using namesp

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha&#39;s staff(几何找规律)

Problem Description "You shall not pass!"After shouted out that,the Force Staff appered in CaoHaha's hand.As we all know,the Force Staff is a staff with infinity power.If you can use it skillful,it may help you to do whatever you want.But now,hi

2017中国大学生程序设计竞赛 - 女生专场(dp)

Building Shops Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 701 Accepted Submission(s): 265 Problem Description HDU's n classrooms are on a line ,which can be considered as a number line. Eac

2017中国大学生程序设计竞赛 - 女生专场 Happy Necklace(递推+矩阵快速幂)

Happy Necklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1146    Accepted Submission(s): 491 Problem Description Little Q wants to buy a necklace for his girlfriend. Necklaces are single

2017中国大学生程序设计竞赛 - 女生专场 Deleting Edges(思维+最短路)

Deleting Edges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 567    Accepted Submission(s): 210 Problem Description Little Q is crazy about graph theory, and now he creates a game about grap

2017广东工业大学程序设竞赛E题(倒水)

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