转自:母函数 入门 + 模板  感谢

在数学中,某个序列的母函数(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个无标志的盒子,盒子允许空,也允许放多于一个球)。

整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做拆分数。

现在以上面的第二种情况每种种类个数无限为例,给出模板:

#include <iostream>
using namespace std;
// Author: Tanky Woo
// www.wutianqi.com
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.wutianqi.com/?p=587

这题大家看看简单不?把上面的模板理解了,这题就是小Case!

看看这题:

2.  题目:http://acm.hdu.edu.cn/showproblem.php?pid=1398

代码:http://www.wutianqi.com/?p=590

要说和前一题的区别,就只需要改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.wutianqi.com/?p=592

这题终于变化了一点,但是万变不离其中。

大家好好分析下,结合代码就会懂了。

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/

Tanky Woo原创文章,转载请注明出处:http://www.wutianqi.com/?p=596

对于任何转载本博客文章且不保留原文链接或任意删改文中链接的行为,本人将一定周旋到底!

母函数(Generation Function) 入门 + 模板的更多相关文章

  1. HDU 1251 统计难题(字典树入门模板题 很重要)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submi ...

  2. hdu 1028 Ignatius and the Princess III(母函数入门+模板)

    Description "Well, it seems the first problem is too easy. I will let you know how foolish you ...

  3. hdu 3549 Flow Problem【最大流增广路入门模板题】

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3549 Flow Problem Time Limit: 5000/5000 MS (Java/Others ...

  4. Django入门--模板标签、继承与引用

    一.模板标签 Django模板引擎提供的可以在模板中进行的各种逻辑操作,是函数调用的一种特殊形式,如循环.判断等功能,期语法规则为: {% tag %} content {% tag 参数1 参数2 ...

  5. 使用std::function改善模板的低效性

    泛型编程中,模板会根据传入类型的不同,生成多种实例,相对低效. 模板编程: #include <iostream> using namespace std; //未使用函数包装器 temp ...

  6. Template function 函数模板用法

    #include<iostream> using namespace std; const double PI = 3.1415926; template <class T> ...

  7. Oracle PLSQL Demo - 29.01.Function结构模板 [无入参] [有返回]

    CREATE OR REPLACE FUNCTION function_name RETURN DATE AS v_date DATE; BEGIN ; dbms_output.put_line(v_ ...

  8. Flask入门模板过滤器与测试器(五)

    1 模板引擎之过滤器 概念 : 过滤器本质上是个转换函数,第一个参数是待过滤的变量.如果它有第二个参数,模板中就必须传进去. 过滤器使用管道符| 放在{{ }} Jinja2模板引擎提供了丰富的内置过 ...

  9. Flask入门模板Jinja2语法与函数(四)

    1 模板的创建 模板文件结构: project/ templates/ 模板文件 跳转模板一般使用: from flask import render_template,render_template ...

随机推荐

  1. ethereum(以太坊)(三)--合约单继承与多继承

    pragma solidity ^0.4.0; // priveta public internal contract Test{ //defualt internal uint8 internal ...

  2. 基本数据类型补充,set集合,深浅拷贝等

    1.join:将字符串,列表,用指定的字符连接,也可以用空去连接,这样就可以把列表变成str ll = ["wang","jian","wei&quo ...

  3. 小程序里面使用wxParse解析富文本导致页面空白等

    在部分安卓手机上会出现白屏的情况且有些ios手机上图文混排上,图片显示不出问题 解决:把插件里面的console.dir去掉即可(原因在于安卓手机无法解析console.dir) 有些图片解析出来下面 ...

  4. php扩展开发-常量

    //常量在内核中的结构 typedef struct _zend_constant { zval value; int flags; char *name; uint name_len; int mo ...

  5. Social Media Addiction【社交媒体上瘾】

    Social Media Addiction Children as young as ten are becoming dependent on social media for their sen ...

  6. Makefile (2) gdb

    gdb调试 1.用debug的方式编译 -g 2.打上断点 3.单步调试 step into 进入函数里面 step over 运行整个函数 step return 跳出当前函数 4.继续运行 5.打 ...

  7. 在WebAPI中调用其他WebAPI

    client.BaseAddress = new Uri("http://xxx.xxx.xx.xx:xxxx/); client.DefaultRequestHeaders.Accept. ...

  8. No module named appium

    在脚本中会有:from appium import webdriver 第一次运行时可能会遇到这样的error:No module named appium 之所以会报这样的error是因为没有装cl ...

  9. compileReleaseJavaWithJavac

    如果你打release 包的时候,出现这个问题,那么请你先跑一下程序,肯定是有什么方法名,或者什么东西没找到. release 的时候不会报错,只有你跑的时候才会报错.

  10. 直接选择排序&堆排序

    1.什么是直接选择排序? 直接选择排序(Straight Select Sort)是一种简单的排序方法,它的基本思想是:通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i ...