该文章建立在你已经看过母函数的相关数学知识的基础上,如果没有看过,建议看一下 hdu 论坛的母函数课件,传送门:http://acm.hdu.edu.cn/forum/read.php?tid=3853

用一个最简单的例子说明代码:

硬币面值有1元、5元、10元、25元、50元,一共5种,对于一个钱数 money,可以有多少中兑现方法?

很容易地构造母函数

G(x) = (x^0 + x^1 + x^2 + …) * (x^0 + x^5 + x^10 + …) * (x^0 + x^10 + x^20 + …)

* (x^0 + x^25 + x^50 + x^75 + …) * (x^0 + x^50 + x^100 + x^150 + …)

数学上的思路就拆开这个多项式因式,看看 x^money 的系数是多少。所以,编程的关键是如何实现拆分?

思路是 先把前面两个因式拆开,得到一个因式,代替第二个因式;然后用第二个因式(求出来的因式)和第三个因式相乘,代替第三个因式;递归计算到最后一个因式,得出结果。

由于便于编程的实现,我们在 G(x) 前面加多一个因式 (1*x^0 + 0*x^1 + 0*x^2 + … ),这个因式为1,所以并不改变母函数的值。把已经计算出来的因式的系数存放到一个数组 a 里面,把当前因式与下一个因式乘起来的因式的系数放到另外一个数组 b 里面。两个因式乘完了,就把 b 数组里面的数据放到 a 数组里面,把 b 数组清空,重复刚才的步骤,直到最后一个因式都乘进去了,才结束。此时,a 数据里面存放的就是拆分开来的多项式的系数。

代码如下:

#define M 500int a[M];
int b[M];void GenerationFunction()
{int cent[5] = {1, 5, 10, 25, 50};memset(a, 0, sizeof(a));memset(b, 0, sizeof(b));a[0] = 1; // 手动添加的一个多项式因式 (1*x^0 + 0*x^1 + 0*x^2 + … )for(int i = 0; i < 5; i ++) // i 指向第几个多项式因式(从0开始算){for(int j = 0; j < M; j ++){   // j 指向已经算出来的因式的指数,a[j] 存放的是指数为 j 的项的系数for(int k = 0; j+k < M; k += cent[i]){   // k 代表下一个因式的指数,因式的指数是隔 cent[i] 递增的。// 另外,因式中,指数为 k 的项的系数为 1b[j+k] += a[j]; // 对于 a[j] * x^j * x^k = a[j] * x^(j+k) // 就把 x^(j+k) 的系数 a[j] 加到 存放当前答案的数组 b 里面}}for(int j = 0; j < M; j ++){ // 把数组 b 元素滚动到 数组 a 去,以便递归进行乘法运算;另外,清空数组 ba[j] = b[j];b[j] = 0;}}
}

  

显而易见,a 数组和 b 数据是滚动操作的,可以用一个二维数组,外加一个滚动变量简单操作:

#define M 500int ans[M];
int f = 0;void GenerationFunction()
{int cent[5] = {1, 5, 10, 25, 50};memset(ans, 0, sizeof(ans));ans[0][0] = 1; // 初始化第一个多项式因式for(int i = 0; i < 5; i ++){for(int j = 0; j < M; j ++){for(int k = 0; j+k < M; k += cent[i]){ans[1-f][j+k] += ans[f][j];}}memset(ans[f], 0, sizeof(ans[f])); // 清空当前数组,留待下一个循环用f = 1 - f; // 修改滚动变量}
}

  

看了两段代码。看过背包的童鞋一般都联想到背包去了。

对于要求的 money ,理解为背包的大小,每种硬币的面值理解为货物的大小,a[i] 就是选择到当前这个硬币,里面放 i 大小货物的方法数。如果题目中硬币无限个,就是完全背包,如果有些限制条件,就是修改版的完全背包。循环到最后,a[money] 就是选择完全部硬币,背包中放 money 大小货物的方法数,也就是把 money 元兑换成各种硬币的方法数。

当然,用母函数的思路理解代码,也是可以的。这样子的话,基本可以解决 hdu 那个课件里面的题目,除了 hdu 2069 Coin Change。

Coin Change 题目中,有一个要求,就是每一种兑换的方式,里面的硬币数量不超过 1000 个。用母函数怎么解决这个问题?参考背包的方法——加多一维!代码如下:

#define M 300int ans[2][M][101];
int f = 0;void GenerationFunction()
{int cent[5] = {1, 5, 10, 25, 50};ans[0][0][0] = 1; // 初始化for(int i = 0; i < 5; i ++){for(int j = 0; j < M; j ++){for(int k = 0; j+k < M; k += cent[i]){for(int g = 0; g+k/cent[i] < 101; g ++){// ans[][j][g] 表示放 j 大小的货物,并且用 g 个物品放,的方法数ans[1-f][j+k][g+k/cent[i]] += ans[f][j][g];}}}memset(ans[f], 0, sizeof(ans[f]));f = 1 - f;}
}

  

看了几个代码,基本上,用母函数的思路敲出来的代码和用背包敲出来代码是基本一样的。这意味着母函数的思路其实是背包思路的一种。如果童鞋对于背包熟的话,基本可以很快地消化母函数的代码,当然,不熟悉背包的话,就像我一样,用母函数的思路敲代码。效果是一样的。

最后,把 hdu 那个课件最后一页的练习题粘到这里来:1028、1709、1085、1171、1398、2069、2152。

本文转自:http://www.cnblogs.com/lijunle/archive/2010/09/04/1817764.html

转载于:https://www.cnblogs.com/Chinese-Coder-Clarence/articles/2154581.html

用母函数的思路解释母函数的代码相关推荐

  1. D. New Year and the Permutation Concatenation 题解翻译+思路解释(官方为主,我为补充)+普通人能看得懂的代码(我照着思路写的哈哈哈)

    传送门:http://codeforces.com/contest/1091/problem/D There are two types of subarrays with length n: 有两种 ...

  2. 【2022年华为杯数学建模E题赛后总结加思路详细介绍配代码----10月11号写的总结】

    提示:下文将介绍2022年华为杯数学建模E题赛后总结加思路详细介绍配代码 傻逼队友,傻逼队友,傻逼队友一定要看好人在进行组队,这是劝告. 这里有几点总结进行描述: 第一,图一定要尽量多,对图的解释要多 ...

  3. 微信公众号网页授权思路解析及具体代码

    微信公众号网页授权思路解析及具体代码 微信开发文档 实现方式也是两种: 1.静默授权登录 授权登录以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静 ...

  4. 2023美国大学生数学建模竞赛C题思路解析(含代码+数据可视化)

    以下为2023美国大学生数学建模竞赛C题思路解析(含代码+数据可视化) 规则: 猜词,字母猜对,位置不对为黄色,位置对为绿色,两者皆不对为灰色. 困难模式下的要求:对于猜对的字母(绿色和灰色),下一步 ...

  5. 【母函数|生成函数】学习母函数

    参考文献(尊重原创): 二项式定理 递归和母函数 母函数(对于初学者的最容易理解的) 例题: 普通母函数: 找单词                   题解 摆花                    ...

  6. java 地铁换乘算法,地铁换乘-一道题目,求思路,不求代码,该怎么处理

    地铁换乘---一道题目,求思路,不求代码 1.地铁换乘 为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示. 线1 苹果园 .... 四惠东 线2 西直 ...

  7. 全国计算机等级考试(2019年版python)用自己的思路编写课后习题代码(6-8章)

    本来想把后面五章的代码一块放进来的,但是吸收了发布前面五章代码的经验,这次在代码的基础上又增加了注释和代码验证结果部分,所以整体看起来6-8章的代码会比较多,但是如果除去这些非必要代码和说明的部分,其 ...

  8. 2020全国大学生数学建模A题思路讲解与核心代码

    2020全国大学生数学建模A题思路讲解与核心代码 题目 核心方法: 问题一 问题二 问题三和问题四 答案如下: 题目 核心方法: 热传导 有限差分法 遍历法 问题一 建立焊接区域中心温度变化规律模型, ...

  9. 全国计算机等级考试(2019年版python)用自己的思路编写课后习题代码(9-10章)

    完结篇啦! 一个阶段的结束象征着另一个阶段的重新开始,未来还要继续加油呀. 下面贴上最后两章的编程题代码,如有错误欢迎指正,不胜感激. 第九章 python标准库概览 #1 使用turtle绘制一个蜂 ...

最新文章

  1. 来者不拒,“昊”课等你——直播微生物篇
  2. Linux-服务器远程控制
  3. 在Bootstrap开发框架中使用bootstrap-datepicker插件
  4. Oracle入门(十四.21)之创建DML触发器:第二部分
  5. MATLAB学习笔记(八)
  6. ACCESS模糊查询出现的变态问题,不知道该问题的希望注意,知道内幕的高手还望给小弟一个解释 Thanks...
  7. cmd上如何运行php文件,cmd - php文件在命令行可以顺利运行,在浏览器上无法正常运行...
  8. 一个问题引发的连环血案
  9. Topological Sorting(拓扑排序)
  10. 高斯 matlab程序,一个计算高斯积分点坐标和权的MATLAB程序
  11. html怎么设置鼠标手势,css怎么设置鼠标手势?
  12. php expecting,php – 解析错误:语法错误,意外的’.’,expecting’,’或’;’
  13. 一个提升n倍效率的写作工具,我咋不知道?
  14. 从底特律的覆灭,反思“珠三角”未来
  15. 读书笔记 - 《斯坦福极简经济学》
  16. python 基于xgboost预测波士顿房价
  17. 适合手机运行的服务器系统,同样2GB内存 手机为啥不如电脑运行好?
  18. C++指针详解2_typedef函数声明类型、sizeof特性简介与数组指针间关系说明
  19. java并发包详解(jdk7)
  20. python matplotlib画图及配色

热门文章

  1. C++ Primer 7.33 练习编写成员函数
  2. Windows Installer (MSI) 详解 参数介绍
  3. 搭建sql注入实验环境(基于windows)
  4. Live555研究之二Sleep实现
  5. GNU make manual 翻译( 一百五十九)
  6. FCKeditor图片上传 进度条不动
  7. perl(Class::MethodMaker) is needed by MySQL-ndb-tools-5.1.21-0.glibc23.i386
  8. 让你的JXTA应用更加安全.建立真正你自己的私有的组!
  9. 使用srvany.exe将任何程序作为Windows服务运行
  10. springboot 远程日志