母函数(Generating function)详解
母函数(Generating function)详解
在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息。使用母函数解决问题的方法称为母函数方法。
母函数可分为很多种,包括普通母函数、指数母函数、L级数、贝尔级数和狄利克雷级数。对每个序列都可以写出以上每个类型的一个母函数。构造母函数的目的一般是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型。
这里先给出两句话,不懂的可以等看完这篇文章再回过头来看:
1.“把组合问题的加法法则和幂级数的乘幂对应起来”
2.“母函数的思想很简单 — 就是把离散数列和幂级数一 一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “
我们首先来看下这个多项式乘法:

母函数图(1)
由此可以看出:
1.x的系数是a1,a2,…an 的单个组合的全体。
2. x^2的系数是a1,a2,…a2的两个组合的全体。
………
n. x^n的系数是a1,a2,….an的n个组合的全体(只有1个)。
进一步得到:

母函数图(2)
母函数的定义
对于序列a0,a1,a2,…构造一函数:

母函数图(3)
称函数G(x)是序列a0,a1,a2,…的母函数。
这里先给出2个例子,等会再结合题目分析:
第一种:
有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来解决这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+1*x^1表示,
1个2克的砝码可以用函数1+1*x^2表示,
1个3克的砝码可以用函数1+1*x^3表示,
1个4克的砝码可以用函数1+1*x^4表示,
上面这四个式子懂吗?
我们拿1+x^2来说,前面已经说过,x表示砝码,x的指数表示砝码的重量!初始状态时,这里就是一个质量为2的砝码。
那么前面的1表示什么?按照上面的理解,1其实应该写为:1*x^0,即1代表重量为2的砝码数量为0个。
所以这里1+1*x^2 = 1*x^0 + 1*x^2,即表示2克的砝码有两种状态,不取或取,不取则为1*x^0,取则为1*x^2
不知道大家理解没,我们这里结合前面那句话:
“把组合问题的加法法则和幂级数的乘幂对应起来“
接着讨论上面的1+x^2,这里x前面的系数有什么意义?
这里的系数表示状态数(方案数)
1+x^2,也就是1*x^0 + 1*x^2,也就是上面说的不取2克砝码,此时有1种状态;或者取2克砝码,此时也有1种状态。(分析!)
所以,前面说的那句话的意义大家可以理解了吧?
几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x^2)(1+x^3)(1+x^4)
=(1+x+x^2+x^4)(1+x^3+^4+x^7)
=1 + x + x^2 + 2*x^3 + 2*x^4 + 2*x^5 + 2*x^6 + 2*x^7 + x^8 + x^9 + x^10
从上面的函数知道:可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2^x^5 项,即称出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分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。

母函数图(4)
以展开后的x^4为例,其系数为4,即4拆分成1、2、3之和的拆分方案数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念"整数拆分"和"拆分数":
所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。
整数划分:http://acm.nyist.net/JudgeOnline/problem.php?pid=90
代码如下:
#include <stdio.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,i,j,k;
int c1[],c2[];
scanf("%d",&n);
for(i=;i<=n;i++)
{
c1[i]=;
c2[i]=;
}
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
for(k=;k+j<=n;k+=i)
{
c2[k+j]+=c1[j];
}
for(j=;j<=n;j++)
{
c1[j]=c2[j];
c2[j]=;
}
}
printf("%d\n",c1[n]);
}
return ;
}
现在以上面的第二种情况每种种类个数无限为例,给出模板:
#include <iostream>
using namespace std;
const int _max = ;
// c1是保存各项质量砝码可以组合的数目
// c2是中间量,保存没一次的情况
int c1[_max], c2[_max];
int main()
{ //int n,i,j,k;
int nNum; //
int i, j, k; while(cin >> nNum)
{
for(i=; i<=nNum; ++i) // ---- ①
{
c1[i] = ;
c2[i] = ;
}
for(i=; i<=nNum; ++i) // ----- ②
{ for(j=; j<=nNum; ++j) // ----- ③
for(k=; k+j<=nNum; k+=i) // ---- ④
{
c2[j+k] += c1[j];
}
for(j=; j<=nNum; ++j) // ---- ⑤
{
c1[j] = c2[j];
c2[j] = ;
}
}
cout << c1[nNum] << endl;
}
return ;
}
我们来解释下上面标志的各个地方:(***********!!!重点!!!***********)
① 、首先对c1初始化,由第一个表达式(1+x+x^2+..x^n)初始化,把质量从0到n的所有砝码都初始化为1.
② 、 i从2到n遍历,这里i就是指第i个表达式,上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。
③、j 从0到n遍历,这里j就是(前面i個表达式累乘的表达式)里第j个变量,(这里感谢一下seagg朋友给我指出的错误,大家可以看下留言处的讨论)。如(1+x)(1+x^2)(1+x^3),j先指示的是1和x的系数,i=2执行完之后变为
(1+x+x^2+x^3)(1+x^3),这时候j应该指示的是合并后的第一个括号的四个变量的系数。
④ 、 k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。
⑤ 、把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的。
咱们赶快趁热打铁,来几道题目:
(相应题目解析均在相应的代码里分析)
1. 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1028
代码:http://www.cnblogs.com/xl1027515989/p/3691069.html
这题大家看看简单不?把上面的模板理解了,这题就是小Case!
看看这题:
2. 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1398
代码:http://www.cnblogs.com/xl1027515989/p/3691058.html
要说和前一题的区别,就只需要改2个地方。 在i遍历表达式时(可以参考我的资料—《母函数详解》),把i<=nNum改成了i*i<=nNum,其次在k遍历指数时把k+=i变成了k+=i*i; Ok,说来说去还是套模板~~~
3. 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1085
代码:http://www.cnblogs.com/xl1027515989/p/3691055.html
这题终于变化了一点,但是万变不离其中。
大家好好分析下,结合代码就会懂了。
4. 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1171
代码:http://www.wutianqi.com/?p=594
还有一些题目,大家有时间自己做做:
HDOJ:1709,1028、1709、1085、1171、1398、2069、2152
(原创文章,欢迎各位转载,但是请不要任意删除文章中链接,请自觉尊重文章版权,违法必究,谢谢合作。Tanky Woo原创, www.WuTianQi.com)
附:
1.在维基百科里讲到了普通母函數、指數母函數、L級數、貝爾級數和狄利克雷級數:
http://zh.wikipedia.org/zh-tw/%E6%AF%8D%E5%87%BD%E6%95%B0
2.Matrix67大牛那有篇文章:什么是生成函数:
http://www.matrix67.com/blog/archives/120
3.大家可以看看杭电的ACM课件的母函数那篇,我这里的图片以及一些内容都引至那。
转载出处:http://www.wutianqi.com/?p=596。
母函数(Generating function)详解的更多相关文章
- Function 详解(一)
一直想写一系列关于javascript的东西,可惜从申请博客以来就一直抽不出时间来好好写上一番,今天终于熬到周末,是该好好整理一下,那么先从声明函数开始吧; 总所周知,在javascript中有匿名函 ...
- Flink DataStream API 中的多面手——Process Function详解
之前熟悉的流处理API中的转换算子是无法访问事件的时间戳信息和水位线信息的.例如:MapFunction 这样的map转换算子就无法访问时间戳或者当前事件的时间. 然而,在一些场景下,又需要访问这些信 ...
- 2.Python函数/方法(method/function)详解
1.什么是函数 它是一段功能代码,理解为一种功能行为,在内存中有空间区域,函数需要被调用才能执行(通过函数名来调用): 好处: 1).提高代码的复用性 2).提升代码的阅读性 3).增加代码的扩展性 ...
- 【转】母函数(Generating function)详解 — TankyWoo(红色字体为批注)
母函数(Generating function)详解 - Tanky Woo 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供 ...
- js Function 加不加new 详解
以下来自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new The new operato ...
- 百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:
原文:百度地图API详解之事件机制,function"闭包"解决for循环和监听器冲突的问题: 百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和D ...
- Java8 (Function,Consumer,Predicate,Supplier)详解
1. https://blog.csdn.net/lzm18064126848/article/details/70199769 1.1 https://blog.csdn.net/turbo_zon ...
- JS函数动作分层结构详解及Document.getElementById 释义 js及cs数据类型区别 事件 函数 变量 script标签 var function
html +css 静态页面 js 动态 交互 原理: js就是修改样式, 比如弹出一个对话框. 弹出的过程就是这个框由disable 变成display:enable. 又或者当鼠标指向 ...
- 详解jquery插件中(function ( $, window, document, undefined )的作用。
1.(function(window,undefined){})(window); Q:(function(window,undefined){})(window);中为什么要将window和unde ...
随机推荐
- 【Nodejs】记一次图像识别的冒险
笔者的团队最近接到了一个有关图像识别的需求,本来应该由后端团队提供能力,native提供容器,前端团队仅负责一些“外围的形式工作”,不过由于各种各样的原因,最后的结果变成了前端团队在原有工作基础上,承 ...
- 最短路 Codeforces Round #103 (Div. 2) D. Missile Silos
题目传送门 /* 最短路: 不仅扫描边,还要扫描点:点有两种情况,一种刚好在中点,即从u,v都一样,那么最后/2 还有一种是从u,v不一样,两种的距离都是l 模板错了,逗了好久:( */ #inclu ...
- Windows 7上安装Microsoft Loopback Adapter(微软环回网卡)
Oracle 安装过程中,先决条件检查遇到如下错误: 正在检查网络配置要求... 检查完成.此次检查的总体结果为: 失败 <<<< 问题: 安装检测到系统的主 IP 地址是 ...
- epoll IO多路复用(异步阻塞AIO)
epoll的异步阻塞(AIO): 用户线程创建epoll后,其实是内核线程负责扫描 fd 列表(在网络服务器上可以是socket,socket在创建后返回的也是文件描述符),并填充事件链表.但是,并不 ...
- 完成fcc作业2时思路
1.设置导航链接按钮栏时,不能用文档流,要用position:fixed;固定在窗口上方, 其他普通流盒子按上下顺序就用position:relative:后面发现导航栏被普通流盒子挡在了下面,就设置 ...
- 提取header头进行模块化处理
在进行爬取网上东西的时候一般网站都做了UA的过滤,解决办法就是在代码中加入. 所以才有了本篇提取header头信息单独写成一个模块或者说是函数/类的想法,直接上示例 1.把UA头信息在浏览器中复制出来 ...
- activity间数据传递
传递简单数据 创建两个activity,FirstActivity和TwoActivity,这里将会将数据从FisrtActivity传给TwoActivity. 创建完activity的目录界面如下 ...
- 【Python-2.7】换行符和制表符
在Python中换行符“\n”表示接下来的内容将会换到下一行显示,制表符“\t”表示下面的内容显示时在前面留出空白,如打印如下内容: Dear: I love you forever! 上面的一段话分 ...
- RabbitMQ调用
添加 gradle依赖complie("com.rabbitmq:amqp-client:5.0.0") Hello, World Working Queues Publish/S ...
- 前端JavaScript入门——JavaScript变量和操作元素
变量JavaScript 是一种弱类型语言,javascript的变量类型由它的值来决定. 定义变量需要用关键字 ‘var’: var a = 123; var b = 'asd'; //同时定义多个 ...