题目描述

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

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

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

3 1
输出样例#1:

1
输入样例#2:

13 2
输出样例#2:

3
输入样例#3:

1000000 5
输出样例#3:

15808
解题思路:

首先明确一点,每个瓶中的水量都是2的幂,这个不难证明。 其次,想要瓶子更少,则要尽可能把瓶子合并,这是什么意思呢? 举个例子,输入N=13,K=2,先不考虑购买新瓶子和K,给出13个瓶子的两种合并方案,4 4 4 1和8 4 1。不废话,后者显然更好。 其实也不难证明上面这条的最优性质,总之,我们总是希望尽可能把多的瓶子合并。 实际算法不难,首先把瓶子先进行合并,最后总会得到一个无法再合并的结果,比如上面的8 4 1,但是这时候我们仍有三个瓶子,而数据要求我们最多剩下2个瓶子,所以我们第二步就是对最后两个瓶子进行合并,这时候直接4-1=3,即所求需要购买的瓶子数,于是最后两个瓶子可以合并为一个蓄水量为8的瓶子。


算法设计也比较简单,我这里用的是递归来实现。


func1(n,r): 返回将n个瓶子存入数组f之后,所使用的数组长度,r传入1。 我们在这个函数中找到小于n的最大的2的幂y,这个数字填充数组当前位置,然后再递归调用func1(n-y,r+1),返回其返回值。 边界条件为n==0,此时直接返回r-1。


func2(n,r): 合并数组f中下标为r~n的瓶子,通常r<=n。 两个边界条件:1.n<r+1,直接返回0,因为n绝对小于r,不需要合并。2.n==r+1,说明要合并的瓶子是相邻的两个,直接将他们合并,然后返回就好了。 如果需要合并且合并的不是相邻两个瓶子,那么我们可以递归地调用func2(n,r+1),这样会把编号为r+1到n的瓶子合并,于是我们就可以直接再把编号为r和r+1的瓶子合并,注意要计算结果。

AC代码:

 #include<cstdio>
#define ll long long
using namespace std;
ll n,k,f[];
int process1(ll n1,ll r) {
if(!n1) return r - ;
ll y = ;
while(true) {
if(y * > n1) break;
y = y + y;
}
f[r] = y;
return process1(n1-y,r+);
}
int process2(ll n2,ll r) {
if(n2 < r + ) return ;
if(n2 == r + ) {
ll y = f[r] - f[n2];
f[r] *= ;
return y;
}
ll u = process2(n2,r+);
ll e = f[r] - f[r+];
f[r] *= ;
return u + e;
}
int main()
{
scanf("%lld%lld",&n,&k);
int t = process1(n,);
int ans = process2(t,k);
printf("%d",ans);
return ;
}

洛谷 P1582 倒水的更多相关文章

  1. 洛谷 P1582 倒水 解题报告

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  2. 洛谷P1582 倒水

    P1582 倒水 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把 ...

  3. 洛谷P1582 倒水 二进制 lowbit __builtin_popcount

    P1582 倒水:https://www.luogu.org/problemnew/show/P1582 题意: 给定n瓶装有1升的水瓶,每次可以把两瓶装水量相同的水和成一瓶,问最少还要增加几瓶装有1 ...

  4. 洛谷 - P1582 - 倒水 - 位运算

    https://www.luogu.org/problemnew/show/P1582 要求用最少的瓶子,那肯定不能有两个一样的瓶子,否则合并更优. 枚举其二进制位,每次加上lowbit,将最后一个1 ...

  5. 洛谷P1582 倒水 二进制的相关应用

    https://www.luogu.org/problem/P1582 #include<bits/stdc++.h> using namespace std; long long N,K ...

  6. 洛谷P1582 倒水题解

    题目 分析 这个题并不难,只是需要仔细思考我们首先可以很轻松的把这个题给疏通一下题意. 1:首先我们最后每个瓶子中装的水一定是一个$2^x$,因为每次都是$2$倍的加,这个应该很好理解. 2:我们要明 ...

  7. 洛谷 P1582 倒水 (二进制)

    这道题实际上是考二进制 很容易看出杯子水量一定是2的i次方 所以n杯水最后剩下的水一定是n用二进制表示中1的个数 所以就枚举n来求什么时候1的个数小于k 那么这里有个优化,不然会超时 因为每次加的目的 ...

  8. Java实现 洛谷 P1582 倒水

    import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import ...

  9. 洛谷P1582——倒水(进制,数学)

    https://www.luogu.org/problem/show?pid=1582 题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了 ...

随机推荐

  1. COJ 1163 乘法逆元的求解

    乘法逆元就是求一个 a/b = c(mod m)在已知a%m , b%m 的条件下 求c的解 #include <cstdio> #include <cstring> usin ...

  2. 听dalao讲课 7.27

    1.高斯消元&线性基 也就是打大暴力啊 所谓的高斯消元也就是加减消元嘛,我的意识流高斯消元是可以的,没听到HY神犇讲,LZHdalao讲得很好,其实就是\(O(n^3)\)的暴力,别的地方一直 ...

  3. 【NOIP2017练习&BZOJ4998】星球联盟(强联通分量,并查集)

    题意: 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流. 但是,组成联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两个 ...

  4. hdu - 3549 Flow Problem (最大流模板题)

    http://acm.hdu.edu.cn/showproblem.php?pid=3549 Ford-Fulkerson算法. #include <iostream> #include ...

  5. [bzoj1895][Pku3580]supermemo_非旋转Treap

    supermemo bzoj-1895 Pku-3580 题目大意:给定一个n个数的序列,需支持:区间加,区间翻转,区间平移,单点插入,单点删除,查询区间最小值. 注释:$1\le n\le 6.1\ ...

  6. Warm up-HUD4612(树的直径+Tarjin缩点)

    http://acm.hdu.edu.cn/showproblem.php?pid=4612 题目大意:求加一条边最小的桥数 先用Tarjin缩点求出一棵树,然后用bfs求出树的直径,树的直径就是加一 ...

  7. 条款十五: 让operator=返回*this的引用

    c++程序员经常犯的一个错误是让operator=返回void,这好象没什么不合理的,但它妨碍了连续(链式)赋值操作,所以不要这样做. 一般情况下几乎总要遵循operator=输入和返回的都是类对象的 ...

  8. cisco PIX

    来自为知笔记(Wiz)

  9. start-all.sh 启动时报错解决方案

    文件拥有者不是当前用户,或者文件权限没有修改权限 解决方法: sudo chmod 777  "文件名" 或者用 su root 登录,然后删除  再 exit Datanote服 ...

  10. Spark修炼之道(基础篇)——Linux大数据开发基础:第二节:Linux文件系统、文件夹(一)

    本节主要内容 怎样获取帮助文档 Linux文件系统简单介绍 文件夹操作 訪问权限 1. 怎样获取帮助文档 在实际工作过程其中,常常会忘记命令的使用方式.比如ls命令后面能够跟哪些參数,此时能够使用ma ...