[Bzoj 1192][HNOI2006]鬼谷子的钱袋(二进制优化多重背包)
(人生第一篇bzoj题解有点激动
首先介绍一下题目:
看它题目那么长,其实意思就是给定一个数a,求将其拆分成n个数,通过这n个数可以表示出1~a中所有数的方案中,求最小的n。
您看懂了嘛?不懂咱来举个栗子:
3可以变为(1,2)两个数(废话,我当然知道),使1,2可以表示出1,2,3这些数字。看到这道题就想到了不久前看到的二进制优化多重背包。简直一模一样。
我们想我们对于一个数P。我们可以将其分成两部分(1~P/2)与(P/2+1,P),我们思考:假设我们已经知道(1~P/2)至少需要m个数,那么我们完全可以在左区间的基础上添加一个P/2这个数,使这m+1个数可以表示(1~P)的所有数,因为(1+P/2~P/2+P/2)=(P/2+1~P)。
我们其实又可以通过手+草稿纸发现关于一个P的最小值n是有(1~P)的左半边区间(1~P/2)的最小值+1有关,而(1~P/2)的最小值又与它本身的左半边区间的值有关,所以事实上这是一个可以递推的过程。
然后我们归纳总结一下——P与P/2有关,P/2又与P/4有关,很容易联想到二进制。我们只要手算过后稍一扩展我们便会发现——关于一个数P,我们使一个数s满足2s -1<P,注意严格小于P,即s为log2(P),那么这一个数P可以被1,2,4.......2s-1,P-2s +1 分解。
那么其实我们很快就可以知道一个数P所对应最小n了,其实就是log2(P)+1.那么这道题一下变得简单了起来,贴代码
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int main()
{
long long a;
scanf("%lld",&a);
printf("%lld",(long long )log2(a)+1);
}
鬼谷子的钱袋
其实这道题在luogu上有加强版本https://www.luogu.org/problem/P2320,其要求输出每个钱袋的数量,这道题也很简单,我们通过上面的推理先求出S,再以此求出1~2s-1 和P-2s+1再排序输出即可(据说原本只有算n,luogu加上了这道题,然而数据貌似有锅)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long p,s,k;
int main()
{
scanf("%lld",&p);
printf("%lld\n",(long long)log2(p)+1);
s=log2(p);
k=p-(1<<s)+1;
for(long long i=0;i<=s-1;i++)
{
if(1<<i>k&&k!=0)
{
printf("%lld ",k);
k=0;
}
printf("%lld ",1<<i);
}
if(k!=0)
printf("%lld ",k);
return 0;
}
鬼谷子的钱袋(加强版
接下来简单描述一下标题所写的二进制优化多重背包
一般来说我们的多重背包的思路是枚举取n个同种物品,转化为01背包
那这样的时间复杂度 O(NV*∑(V/W[i])).(V为体积,W[i]为每件的费用)
但假如我们将每件物品都像鬼谷子的钱袋一样二进制拆分,那每一个物品都会被拆成log2(W[i])+1个物品
那这样再做01背包所要的时间复杂度为 O(V*log(W[i])+V)(PS:这个时间复杂度有可能写错了,但是应该差不多)
关于二进制优化多重背包以后我会再写一篇博客来讲,这篇主要的是题解hhh
您理解了嘛,慢走。
不理解的可以加qq2733524923我们一起探讨哦
[Bzoj 1192][HNOI2006]鬼谷子的钱袋(二进制优化多重背包)的更多相关文章
- BZOJ 1192: [HNOI2006]鬼谷子的钱袋 数学结论
1192: [HNOI2006]鬼谷子的钱袋 Description 鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政.有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的 ...
- BZOJ 1192: [HNOI2006]鬼谷子的钱袋(新生必做的水题)
1192: [HNOI2006]鬼谷子的钱袋 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3557 Solved: 2596[Submit][St ...
- BZOJ 1192 [HNOI2006]鬼谷子的钱袋:二进制 砝码称重问题
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1192 题意: 鬼谷子带了a元钱,他要把a元钱分装在小袋子中,使得任意不大于a的数目的钱,都 ...
- bzoj 1192: [HNOI2006]鬼谷子的钱袋 思维_二进制
十分巧妙的一道题. 考虑当前凑出$[1,i/2)$,那么再有一个 $i/2$,就可以凑出 [i/2+1,i). 注意,这里的 $i$ 都是 2 的 $k$ 次幂. 于是,我们只要找到 $i$ 使得 2 ...
- BZOJ 1192: [HNOI2006]鬼谷子的钱袋 [娱乐]
题意: n个数分组,使得小于n的每个数都能表示出来,最少几组 就是“最优集合”的超级弱化版.....每次+=now+1 然后一个貌似科学的方法是n二进制拆分 #include <iostream ...
- 1192: [HNOI2006]鬼谷子的钱袋
1192: [HNOI2006]鬼谷子的钱袋 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3530 Solved: 2575[Submit][St ...
- poj1014二进制优化多重背包
Dividing Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 53029 Accepted: 13506 Descri ...
- 51nod 1086 背包问题 V2(二进制优化多重背包)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1086 题解:怎么用二进制优化多重背包,举一个例子就明白了. ...
- POJ - 1276 二进制优化多重背包为01背包
题意:直接说数据,735是目标值,然后3是后面有三种钱币,四张125的,六张五块的和三张350的. 思路:能够轻易的看出这是一个多重背包问题,735是背包的容量,那些钱币是物品,而且有一定的数量,是多 ...
随机推荐
- pycharm安装第三方库
https://jingyan.baidu.com/article/4853e1e54b845e1909f7268f.html
- selenium3 利用cookie实现免登陆
1.首先访问要操作的页面 2.登陆一次,使用Fiddle等工具抓取出cookie 3.按照如下代码,即可成功登陆 from selenium import webdriver url = " ...
- 【Spring】重新认识 IoC
前言 IoC (Inversion of control) 并不是Spring特有的概念. IoC 维基百科的解释: In software engineering, inversion of con ...
- LeetCode:“剑指 Offer”
LeetCode:"剑指 Offer" 刷题小菜鸡,花了几天时间做了一遍 LeetCode 上给出的 "剑指 Offer" 在此做一下记录 LeetCode主页 ...
- 封装一个简单的ajax请求
记录自己第一次封装ajax,肯定有很多考虑不周到,如有错误请指出,本人必将虚心改正. /** * * @param {Object} obj =>header:请求头:url:请求地址:meth ...
- Gitlab Burndown Chart
一.说明 通过调用gitlab api直接获取相应project的所有issues,然后对其进行统计以制作燃尽图 二.方法 1.生成 Personal access token Gitlab > ...
- springboot读取配置文件中的信息
在一个项目中,我们有时候会把一些配置信息写入到一个配置文件中,在java代码中读取配置文件的信息.在此记录下读取属性文件中的内容. 在springboot项目中,springboot的配置文件可以使用 ...
- [BZOI2014]大融合——————线段树进阶
竟然改了不到一小时就改出来了, 可喜可贺 Description Solution 一开始想的是边两侧简单路径之和的乘积,之后发现这是个树形结构,简单路径数就是节点数. 之后的难点就变成了如何求线段树 ...
- 玩转C语言链表-链表各类操作详解
链表概述 链表是一种常见的重要的数据结构.它是动态地进行存储分配的一种结构.它可以根据需要开辟内存单元.链表有一个"头指针"变量,以head表示,它存放一个地址.该地址指向一个元素 ...
- MyBatis源码分析(八):设计模式
Mybatis中用到的设计模式 1. 建造者(Builder)模式: 表示一个类的构建与类的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步创建一个复杂的对象,他只允许用户只通过指 ...