【hdoj_1085】Holding Bin-Laden Captive![母函数]
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1085
可以这样理解题意:给出1元,2元和5元的三种硬币若干,每种硬币数量给出,现在可以从所有的硬币中,选出若干(三种中的若干种,若干个)组合出一定的金额,待求的是不能组合出来的金额的最小值.
例如
题目给出的测试例题中,三种硬币数量分别为1,1,3,则题目抽象成数学问题为:
(1+x)(1+x^2)(1+x^5+x^10+x^15)的乘积展开式中,按照次数递增的顺序排列,第一个系数为0的项的次数是多少次?
展开之后,可以发现,1,x,x^2,x^3都存在,x^4不存在,所以,结果为4.
再例如
三种硬币的数量分别为2,1,2,则(1+x+x^2)(1+x^2)(1+x^5+x^10),展开式中1,x,...,x^14(最高次项)都存在,系数都不为0,所以,第一个系数为0的项为x^15,所以,结果为15.
思路:给出三种硬币的数量分别为n1,n2,n5,则最大金额为max=1*n1+2*n2+5*n5,最小金额为0,如果中间缺省一些金额,则求出最小的缺省的金额,如果中间不缺省,则题目所求的最小值为max+1.
直观理解的C++代码如下:
#include<iostream>
using namespace std; int main()
{
int n1,n2,n5;
while(1)
{
cin >> n1 >> n2 >> n5;
if(!n1 && !n2 && !n5)//结束条件
break; int c[10000] = {0};//若money表示金额,则c[money]值的意思是组成金额money共有几种可能的组合,如果为0,则不能组成这种金额. for(int i=0;i<=n1;i++)
for(int j=0;j<=n2;j++)
for(int k=0;k<=n5;k++)//(每种硬币最少可以选择0个,最多可以选择n_i个)
{
int money = 1*i + 2*j + 5*k;//在选择i个1,j个2和k个5的情况下的金额
c[money] += 1;//组成金额money的可能方法+1
}
int max = 1*n1+2*n2+5*n5;//最大金额
int ok = 0;//开关变量
for(int m=0;m<=max;m++)
if(!c[m])//如果第m项系数为0
{
cout << m << endl;//输出这个结果
ok = 1;
break;
}
if(!ok)//如果0~max的项的系数均非0
cout << max+1 << endl;
} return 0;
}
上述代码提交,提示超时.因为,代码中含有三层循环,而每层循环的最大次数为1000次,所以最大总共循环次数为10^9.
简化的做法是将三层循环分布化为两层循环,(A)(B)(C)可以先计算A和B组合的结果D,再计算D和C组合的结果.
如何用代码实现?看一个例子:
1个1元,1个2元,3个5元,则:
首先,单独用一种硬币可以组合的金额对应的方法种类数分别为:
只用1元的:a[0] = 1,a[1] = 1;
只用2元的:b[0] = 1,b[1] = 0,b[2] = 1;
只用5元的:c[0] = 1,c[1~4] = 0,c[5] = 1,c[6~9] = 0,c[10] = 1,c[11~14] = 0,c[15]=1;
然后,组合1元和2元的:
d[0] = a[0]*b[0] = 1;
d[1] = a[0]*b[1] + a[1]*b[0] = 1;
d[2] = a[0]*b[2] = 1;
d[3] = a[1]*b[2] = 1;
之后,再将上面的结果与5元的组合:
e[0] = d[0]*c[0] = 1;
e[1] = d[1]*c[0] = 1;
e[2] = d[2]*c[0] =1;
e[3] = d[3]*c[0] = 1;
e[4] = 0(没有方法可以组合得到4)
......
上述过程的C++代码如下:
#include<iostream>
using namespace std; int main()
{
int num_1,num_2,num_5;
while(1)
{
cin >> num_1 >> num_2 >> num_5;
if(!num_1 && !num_2 && !num_5)//结束条件
break; int a[10000]={0},b[10000]={0},c[10000]={0},d[10000]={0},e[10000]={0};
int i,j; //初始化:只用一种硬币,可以组合成的金额对应的方法种类数
for(i=0;i<=num_1;i++)
a[i] = 1;
for(i=0;i<=num_2;i++)
b[2*i] = 1;
for(i=0;i<=num_5;i++)
c[5*i] = 1; //1和2组合的结果
for(i=0;i<=num_1;i++)
for(j=0;j<=num_2;j++)
d[i+2*j] += a[i] * b[2*j];
//[注意]a[i]*b[2*j]中间的乘号:i对应a[i]种方法,2*j对应b[2*j]中方法,所以i+2*j对应a[i]*b[2*j]种方法 //1和2组合之后,再与5组合的结果
for(i=0;i<=num_1+2*num_2;i++)
for(j=0;j<=num_5;j++)
e[i+5*j] += d[i] * c[5*j]; int max = num_1 + 2*num_2 + 5*num_5; /*输出各项系数(组合成这种金额的方法种类数)
for(i=0;i<=max;i++)
cout << e[i] << " ";
cout << endl;
*/ int ok = 0;
for(i=0;i<=max;i++)
if(!e[i])
{
cout << i << endl;
ok = 1;
break;
}
if(!ok)
cout << max+1 << endl;
} return 0;
}
上述代码,提交AC.
总结和注意:
1.本题用到组合数学的思想,第一种代码(三层循环)有助于理解思路,第二种代码,无非将()()()的过程拆分成两部分,从而避免过多循环.在代码实现时候,可以用一个难度适中的实例,手动计算整个过程,有助于理解写代码.
2.第二种代码中,【注意】
【hdoj_1085】Holding Bin-Laden Captive![母函数]的更多相关文章
- HDU 1085 Holding Bin-Laden Captive!(母函数,或者找规律)
Holding Bin-Laden Captive! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- hdu 1085 Holding Bin-Laden Captive! (母函数)
//给你面值为1,2,5的三种硬币固定的数目,求不能凑出的最小钱数 //G(x)=(1+x+...+x^num1)(1+x^2+...+x^2num2)(1+x^5+,,,+x^5num3), //展 ...
- 杭电ACM分类
杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...
- A过的题目
1.TreeMap和TreeSet类:A - Language of FatMouse ZOJ1109B - For Fans of Statistics URAL 1613 C - Hardwood ...
- 转载:hdu 题目分类 (侵删)
转载:from http://blog.csdn.net/qq_28236309/article/details/47818349 基础题:1000.1001.1004.1005.1008.1012. ...
- 缓冲区溢出利用——捕获eip的傻瓜式指南
[译文] 摘要:为一个简单的有漏洞程序写一个简单的缓冲区溢出EXP,聚焦于遇到的问题和关键性的教训,提供详细而彻底的描述 内容表:1. I pity the fool, who can't smash ...
- 用主题模型可视化分析911新闻(Python版)
本文由 伯乐在线 - 东狗 翻译,toolate 校稿.未经许可,禁止转载!英文出处:blog.dominodatalab.com.欢迎加入翻译小组. 本文介绍一个将911袭击及后续影响相关新闻文章的 ...
- How do I learn mathematics for machine learning?
https://www.quora.com/How-do-I-learn-mathematics-for-machine-learning How do I learn mathematics f ...
- Labeled Faces in the Wild 人脸识别数据集 部分测试数据
development test set Note: images displayed are original (non-aligned/funneled) images. match pairs ...
随机推荐
- Linux之ioctl20160705
ioctl(fdAcodec, ACODEC_GET_ADCL_VOL, &vol_ctrl)//从内核驱动中获取或者设置数据//内核驱动中也使用ACODEC_GET_ADCL_VOL进行ca ...
- https客户端遇到过的问题
1.用.p12格式的证书,在windows上调试完全没问题,在Linux服务器上,提示无效证书格式. 解决方法:将.p12格式的证书转换为.jks格式的证书. 将.p12格式的证书转换为.jks格式的 ...
- Spring源码解析-Advice中的Adapter模式
在spring中与通知相关的类有: 以Advice结尾的通知接口 MethodBeforeAdvice AfterReturningAdvice ThrowsAdvice 以Inter ...
- android 自定义控件---圆形方向盘
在做Android平台开发的时候,经常会遇到安卓原生控件无法满足需求的情况,安卓允许开发者去继承已经存在的控件或者实现你自己的控件. 先来看一下效果图 采用直接集成View类,重写onDrow方法绘制 ...
- PIP 批量更新改为清华这边的镜像更新
之前pip批量更新的时候发现有些包无法更新,而且速度也特别慢,今天尝试了下清华的镜像,速度是真快 # coding=utf-8import pipfrom subprocess import call ...
- mysql的数据库 索引
1.两种主要的引擎:MyISAM和InnoDB 2.如何查看自己的表是什么类型:http://www.cnblogs.com/luosongchao/archive/2013/05/23/309592 ...
- LightOJ 1375 - LCM Extreme 莫比乌斯反演或欧拉扩展
题意:给出n [1,3*1e6] 求 并模2^64. 思路:先手写出算式 观察发现可以化成 那么关键在于如何求得i为1~n的lcm(i,n)之和.可以知道lcm(a,b)为ab/gcd(a,b) 变换 ...
- String.replaceAll()方法替换字符串中的反斜杠(\)
replaceAll()方法实际是采用正则表达式的规则去匹配的. 在regex中"\\"表示一个"\",在java中一个"\"也要用&quo ...
- UITableViewController的使用
如果整个程序界面都只是使用UITableView来搭建,一般需要如下步骤: (1)向界面上拖一个UITableView (2)设置数据源 (3)设置代理 (4)遵守代理协议 上述过程相对繁琐,为了简 ...
- 【BZOJ4816】【SDOI2017】数字表格 [莫比乌斯反演]
数字表格 Time Limit: 50 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Doris刚刚学习了fibonac ...