母函数理解及整数拆分
母函数的定义以及整数拆分模板 母函数(Generating function)详解
在数学中,某个序列的母函数是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息。使用母函数解决问题的方法称为母函数方法。
母函数可分为很多种,包括普通母函数、指数母函数、L级数、贝尔级数和狄利克雷级数。对每个序列都可以写出以上每个类型的一个母函数。构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型。
由此可以看出:
1. x的系数是a1,a2,…an的单个组合的全体。
2. x2的系数是a1,a2,…a2的两个组合的全体。
………
n. xn的系数是a1,a2,….an的n个组合的全体(只有1个)。
由此得到:
母函数的定义:
对于序列a0,a1,a2,…构造一函数:
称函数G(x)是序列a0,a1,a2,…的母函数
这里先给出2个例子,等会再结合题目分析:
第一种:
有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来接吻这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+x表示,
1个2克的砝码可以用函数1+x2表示,
1个3克的砝码可以用函数1+x3表示,
1个4克的砝码可以用函数1+x4表示,
上面这四个式子懂吗?
我们拿1+x2来说,前面已经说过,x表示砝码,x的指数表示重量,即这里就是一个质量为2的砝码,那么前面的1表示什么?1代表重量为2的砝码数量为0个。(理解!)
不知道大家理解没,我们这里结合前面那句话:
"把组合问题的加法法则和幂级数的t的乘幂的相加对应起来"
1+x2表示了两种情况:1表示质量为2的砝码取0个的情况,x2表示质量为2的砝码取1个的情况。
这里说下各项系数的意义:
在x前面的系数a表示相应质量的砝码取a个,而1就表示相应砝码取0个,这里可不能简单的认为相应砝码取0个就该是0*x2(想下为何?结合数学式子)。
Tanky Woo 的程序人生:http://www.wutianqi.com/
所以,前面说的那句话的意义大家可以理解了吧?
几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x2)(1+x3)(1+x4)
=(1+x+x2+x3)(1+x3+x4+x7)
=1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10
从上面的函数知道:可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1;同样,6=1+2+3=4+2;10=1+2+3+4。
故称出6克的方案有2,称出10克的方案有1 。
接着上面,接下来是第二种情况:
求用1分、2分、3分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。
以展开后的x4为例,其系数为4,即4拆分成1、2、3之和的拆分数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念整数拆分和拆分数:
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
现在以上面的第二种情况每种种类个数无限为例,给出模板:
模板
关于什么是母函数 , 以及在现实生活中的应用 , 请大家详看 或者 HDU 母函数 PPT:
http://www.cppblog.com/MiYu/archive/2010/08/05/122290.html
对于给出的母函数模板 , 让人理解起来比较费劲的!以下给出几种解释 , 和自己理解
//made by syx
//time 2010年9月11日 10:17:27
//母函数例题
/*//整数拆分模板
#include <iostream>
using namespace std;
const int lmax=10000;
//c1是用来存放展开式的系数的,而c2则是用来计算时保存的,
//他是用下标来控制每一项的位置,比如 c2[3] 就是 x^3 的系数。
//用c1保存,然后在计算时用c2来保存变化的值。
int c1[lmax+1],c2[lmax+1];
int main()
{
int n, i, j, k ;
// 计算的方法还是模拟手动运算,一个括号一个括号的计算,
// 从前往后
while ( cin>>n )
{
//对于 1+x+x^2+x^3+ 他们所有的系数都是 1
// 而 c2全部被初始化为0是因为以后要用到 c2[i] += x ;
for ( i=0; i<=n; i++ )
{
c1[i]=1;//蓝色字体表示埋葬个人理解的第一次运行的意义
c2[i]=0;//第一次运行 表示出第一个式子的各项系数放进c1
}
//第一层循环是一共有 n 个小括号,而刚才已经算过一个了
//所以是从2 到 n
for (i=2; i<=n; i++)//第一个式子表示完毕 从第二个式子开始乘 一共有n个括号
{
// 第二层循环是把每一个小括号里面的每一项,都要与前一个
//小括号里面的每一项计算。
for ( j=0; j<=n; j++ )//j是控制的第一个式子中的每一项(即前一个式子)
//第三层小括号是要控制每一项里面 X 增加的比例
// 这就是为什么要用 k+= i ;
for ( k=0; k+j<=n; k+=i )//k是控制第二个式子中的系数(后一个式子)
{ //而且要保持次数不会超过n 因为最多分解为x的
//n次方即 表示1个质量为n的砝码
// 合并同类项,他们的系数要加在一起,所以是加法,呵呵。
// 刚开始看的时候就卡在这里了。
c2[ j+k] += c1[ j];//把乘的的结果即系数的变化放进c2
}
// 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项。
for ( j=0; j<=n; j++ )
{
c1[j] = c2[j] ;
c2[j] = 0 ;
}
}
cout<<c1[n]<<endl;
}
return 0;
}
这句 c2[j+k] += c1[j];的理解还要自己好好的体会体会啊!
*/
自己理解:对于(#式) (1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....).....
第一个for给c1 和 c2 赋值 , 把上面#式的第一个括号(1+x+x^2+x^3+x^4+x^5+....)的系数给放在c1中,
从而再次计算从 # 的 第二个括号开始 , 所以 i 就是代表的# 式第几个括号,
而 用程序模拟手工计算 , 就是 先计算第一个括号 与 第二个括号 计算 , 把结果放到c2中,
在把结果与第三个括号计算 , 把结果放到c2中 , 在和第四个括号计算,........
所以j 就是指的 已经计算出 的 各项的系数 ,比如第一次之后 1+x+x^2+x^3+x^4+x^5+... , j=0指向1 ,
j=2 指向x , .... , 而 k 就是指 将要计算的那个括号中的项 , 因为第i个括号 , 中的指数为0 , i , 2i....所以 k要 + i ;
而结果 c2[j+k] += c1[j]; 就是把 以计算出的 j项的系数 和 现在正在计算的括号的k项相乘 , 所以指数为j+k , 所以结果放到c2[j+k] 中 , 这就是这几个for的作用!
最后刷新下结果 , 下一组数据计算!
埋葬个人的理解
对于(#式) (1+x+x^2+x^3+x^4+x^5+....)*(1+x^2+x^4+x^6+x^8+x^10+....)*(1+x^3+x^6+x^9+x^12....).....
1第一个for给c1 和 c2 赋值 , 把上面#式的第一个括号(1+x+x^2+x^3+x^4+x^5+....)的系数给放在c1中,
从而再次计算从 # 的 第二个括号开始 ,
所以 i 就是代表的# 式第几个括号
2 j即第i个式子中的第j项
3而 k 就是指 将要计算的那个括号中的项 , 因为第i个括号x中的指数为0 , i , 2i....所以 k要 + i ;
4 c2[ j+k] += c1[ j];
c2[j] c1 [j]是指 即次数为j的系数;
c1是用来存放展开式的系数的 而c2则是用来计算时保存的
这里指c1[j]乘以k之后 次数也变成了j+k, 故c2[j+k]的系数要增加c1[j]个;
5 n是砝码的个数
新例题:hdu1085 用1 2 5的硬币买不到的东西的价值(输出最小的)3者数量分别为num1 num2 num3
#include "stdio.h"
int c1[10000],c2[10000];
int main()
{
int i,j,k,num1,num2,num3,n;
while(scanf("%d %d %d",&num1,&num2,&num3)!=EOF)
{
if(!num1&&!num2&&!num3) break;
n=num3*5+num2*2+num1;
for(i=0;i<=n;i++)
{
c1[i]=0;
c2[i]=0;
}
for (i=0;i<=num1;i++)
c1[i]=1;
for(j=0;j<=num1;j++)
// for (k=0;k+j<=num2*2;k=k+2)//num2*2表示最多可能达到的次数
for (k=0;k<=num2*2;k=k+2)//num2*2表示最多可能达到的次数
{ //注意 这里不要用k+j<=num2 因为以前求整数拆分输入数n 要保证次数小于n 因为最大为
//x的n次方 表示为1个重为n的砝码 这里是求多项式相乘 不用限制了
c2[j+k]+=c1[j];
}
for (j=0;j<=num2*2+num1;j++)//因为 下面的c2[j] 中的下标最大为j+k 由上一步可以看出 而j最大为num1 k最大为num2*2
{
c1[j]=c2[j];
c2[j]=0;
}
for(j=0;j<=num2*2+num1;j++)//num1和num2*2不一定那个大那 要表示出所有的项数 所以要这样
for(k=0;k<=num3*5;k+=5)
c2[j+k]+=c1[j];
for (j=0;j<=num3*5+num2*2+num1;j++)
{
c1[j]=c2[j];
c2[j]=0;
}
for (i=0;i<=n;i++)
if(!c1[i]) {printf("%d\n",i);break;}
if(i==n+1) printf("%d\n",i);
}
}
说白了就是求多项式的值
母函数理解及整数拆分相关推荐
- 母函数——整数拆分(HDOJ2152)
最近看到了一些关于母函数的题目,去网上找了一些材料,加上自己的理解,现在可以解决一些简单的问题.那么什么是母函数?其实这个问题我也没有怎么搞懂,通过几个例子来说明一下.下面是转载的一个介绍 http: ...
- 整数拆分的两种解法(已完成)
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 整数拆分 ...
- 整数拆分 python_LeetCode 343. 整数拆分 | Python
343. 整数拆分 题目 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 ...
- 数学上的整数拆分问题
整数拆分是一个经典的数学问题,我们从小学奥数,一直到大学的组合数学,可能都会遇到.从字面意思来看,是将一个整数拆分成若干整数之和,求的是不同的方案个数.我今天想讨论的问题是 " 无序拆分 & ...
- 整数拆分问题的四种解法
整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m ...
- 知识点 - 分拆数/整数拆分
知识点 - 分拆数/整数拆分 解决问题类型: 将一个数用一个或多个正整数的无序和来表示有几种方案. 这是一个母函数的应用,利用了母函数的指数系数是五边形数来优化复杂度. 结论 (1)称正整数n分解为r ...
- 动态规划 - 整数拆分
对于动态规划的思路,在这就不多说了,需要理解的看下这一篇文章动态规划步骤, 下面直接进入主题,利用动态规划思路来解决343. 整数拆分 - 力扣(LeetCode). 第一步.确定数组dp ...
- python 整数 拆分 分段
整数 拆分 分段 不平均分 int1 = 68 # 整数 sub = 3 # 要分成几段 interval = int1 // sub rem = int1 % sub print("余数: ...
- LeetCode-动态规划基础题-343. 整数拆分
描述 343. 整数拆分 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化. 返回你可以获得的最大乘积. 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 ...
- python分割数字_python实现整数拆分,输出拆分序列
昨天笔试VIPKID有一道关于整数拆分的题目,要求输出拆分后的序列,当时没有做出来,记录一下可以实现的想法: 题目示例: 从键盘读入一个数 n, 输出所有和为 n 的子序列和,包括 n 测试用例: 输 ...
最新文章
- php 接收curl json数据格式,curl发送 JSON格式POST数据的接收,以及在yii2框架中的实现原理【精细剖析】...
- iPhone 的 Push(推送通知)功能原理浅析
- 先河系统为你讲解私有云服务器的优点
- 单摆运动属于什么现象_物理模型中的隐含条件是什么
- 百度ERNIE新突破!登顶中文医疗信息处理权威榜单CBLUE冠军
- 44.mysqlbinlog
- 银监会再出新规!银行数据治理与监管评级挂钩
- Delphi2010Excel导入数据库
- 如何修改Maven本地仓库位置
- QT+SQL Server实现车辆管理系统 -代码具体实现
- SIM868模块+Arduino将位置信息上传到服务器
- Java计算两点间的距离
- 解除开启全局 UWP应用网络隔离限制
- 三角学(一)公式,恒等式,函数和难题
- 买房贷款月供怎么算?贷款利息是多少?
- 理想中2.5D的网络拓扑图
- Cookie加密10
- 苏州博物馆计算机系统操作工,行车及铁钢包调度系统在炼钢厂应用.doc
- CTC Loss (一)
- 编程序也得劳逸结合,不能太累。。。
热门文章
- php a标签加nofollow,Z-Blog给文章所有的站外a链接添加nofollow的方法
- 德州仪器发布99%高效GaN逆变器功率级的参考设计
- 网站获取微信授权登录功能
- storage ( initial 64K minextents 1 maxextents unlimited );
- html打砖块游戏制作,JavaScript实现打砖块游戏
- 程序人生 - 创可贴使用不当或致截肢
- “约定优于配置”与Magento总结
- css 页面设计,60个精品CSS网页设计欣赏
- php天籁吉他乐器介绍网站系统
- 规则库捕获漏洞信息专用脚本