算法总结之母函数
2014-07-31 08:12
211 查看
1.概念
生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。生成函数有普通型生成函数和指数型生成函数两种,其中普通型用的比较多。形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题。母函数还可以解决递归数列的通项问题(例如使用母函数解决斐波那契数列的通项公式)。
2.组合问题中的应用
先放两句百度百科上的原话:
1.“把组合问题的加法法则和幂级数的乘幂对应起来”
2.“母函数的思想很简单 — 就是把离散数列和幂级数一 一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “
再放两个可以用母函数解决的问题:
问题1:有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?每种重量各有几种可能方案?
问题2:求用1分、2分、3分的邮票贴出不同数值的方案数(邮票个数没有限制)?
从这两个问题可以看出来,用母函数是用来解决:
有N种重量的物品,每种物品有M个(1-无穷),求可以组合出来的重量的个数和该重量的方案数。
和背包问题分类类似,我们可以把这些问题分为:01(每个物品只有一件),完全(每个物品不限量),多重(每个物品都有指定的个数),混合。。
3.问题分析
先来假设一个母函数:G(x)=a0*X^0+a1*X^1+a2*X^2+a3*X^3+...+an*X*n
1)问题1:
再假设一个函数:G(x)=(1+X^1)(1+X^2)(1+X^3)(1+X^4)
其中(1+X^1)可以看做是 (1*X^0+1*X^1)==>{不使用1克的砝码,使用1克的砝码}
那么将多项式分解后:G(x)=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
就将所有砝码使用与否的情况都考虑到了。
这时,函数中的 2*X^3 就代表了 有两种方案可以组成3(3=3;3=1+2)..
那么G(x)中系数不为零的X^P,代表P可以被组合出来,系数为可以组合的方案数。
2)问题2:
同假设一个函数:G(x)=(1+X^1+X^2+X^3+...)(1+X^2+X^4+X^6+...)....
其中(1+X^2+X^4+X^6+...)可以看做{不使用1毛的邮票,使用1个1毛的邮票,使用2个1毛的邮票...}
分解后类似于问题1中的G(x)=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
后函数中X的系数与指数与问题1中的所代表的相同。
3)扩展:
由问题2中的:其中(1+X^2+X^4+X^6+...)可以看做{不使用1毛的邮票,使用1个1毛的邮票,使用2个1毛的邮票...}
可以推论:当重量为N的物品,有M个时,可以写成(1+X^N+X^2N+X^3N+...+X^MN)
3.代码实现
转载自Tanky Woo博客
4.代码详解
我们需要把一个形如G(x)=(1+X^1+X^2+X^3+...)(1+X^2+X^4+X^6+...)....这样的函数
转换成形如F(x)=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)初始化F(x)= “G(x)的第一个括号中的内容” 代码中备注为①
2)将G(x)的第二个括号乘入F(x)中 [b]代码中备注为[/b]②
(1)将F(x)中第一项与G(x)中第二个括号的每一项相乘 [b][b]代码中备注为[/b][/b]③④
[b](2)将F(x)中第二项与G(x)中第二个括号的每一项相乘[/b]
[b] .....[/b]
[b] 3)[b]将G(x)的第三个括号乘入F(x)中[/b][/b]
[b][b] 4)[b]将G(x)的第四个括号乘入F(x)中[/b][/b][/b]
[b][b][b] ...[/b][/b][/b]
[b][b][b] 备注:[/b][/b][/b]
[b][b][b] 1) C1[i]中存的是 X^i的系数,C2[]为临时数组,用来保证C1[]的正确性。[/b][/b][/b]
[b][b][b] 2)根据题目给的物品重量的不同,初始化会不同,且后面的for()的累加也不同。[/b][/b][/b]
[b][b][b]5.相关练习[/b][/b][/b]
[b][b][b] [b][b][b][b]HDU1398 Square Coins[/b][/b][/b][/b][/b][/b][/b]
[b][b][b] HDU1028 Ignatius and the Princess III[/b][/b][/b]
[b][b][b] HDU1085 Holding Bin-Laden Captive![/b][/b][/b]
[b][b][b] HDU1171 Big Event in HDU[/b][/b][/b]
生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具。生成函数有普通型生成函数和指数型生成函数两种,其中普通型用的比较多。形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题。母函数还可以解决递归数列的通项问题(例如使用母函数解决斐波那契数列的通项公式)。
2.组合问题中的应用
先放两句百度百科上的原话:
1.“把组合问题的加法法则和幂级数的乘幂对应起来”
2.“母函数的思想很简单 — 就是把离散数列和幂级数一 一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “
再放两个可以用母函数解决的问题:
问题1:有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?每种重量各有几种可能方案?
问题2:求用1分、2分、3分的邮票贴出不同数值的方案数(邮票个数没有限制)?
从这两个问题可以看出来,用母函数是用来解决:
有N种重量的物品,每种物品有M个(1-无穷),求可以组合出来的重量的个数和该重量的方案数。
和背包问题分类类似,我们可以把这些问题分为:01(每个物品只有一件),完全(每个物品不限量),多重(每个物品都有指定的个数),混合。。
3.问题分析
先来假设一个母函数:G(x)=a0*X^0+a1*X^1+a2*X^2+a3*X^3+...+an*X*n
1)问题1:
再假设一个函数:G(x)=(1+X^1)(1+X^2)(1+X^3)(1+X^4)
其中(1+X^1)可以看做是 (1*X^0+1*X^1)==>{不使用1克的砝码,使用1克的砝码}
那么将多项式分解后:G(x)=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
就将所有砝码使用与否的情况都考虑到了。
这时,函数中的 2*X^3 就代表了 有两种方案可以组成3(3=3;3=1+2)..
那么G(x)中系数不为零的X^P,代表P可以被组合出来,系数为可以组合的方案数。
2)问题2:
同假设一个函数:G(x)=(1+X^1+X^2+X^3+...)(1+X^2+X^4+X^6+...)....
其中(1+X^2+X^4+X^6+...)可以看做{不使用1毛的邮票,使用1个1毛的邮票,使用2个1毛的邮票...}
分解后类似于问题1中的G(x)=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
后函数中X的系数与指数与问题1中的所代表的相同。
3)扩展:
由问题2中的:其中(1+X^2+X^4+X^6+...)可以看做{不使用1毛的邮票,使用1个1毛的邮票,使用2个1毛的邮票...}
可以推论:当重量为N的物品,有M个时,可以写成(1+X^N+X^2N+X^3N+...+X^MN)
3.代码实现
转载自Tanky Woo博客
#include <iostream> using namespace std; // Author: Tanky Woo // www.wutianqi.com const int _max = 10001; // 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=0; i<=nNum; ++i) // ---- ① { c1[i] = 1; c2[i] = 0; } for(i=2; i<=nNum; ++i) // ----- ② { for(j=0; j<=nNum; ++j) // ----- ③ for(k=0; k+j<=nNum; k+=i) // ---- ④ { c2[j+k] += c1[j]; } for(j=0; j<=nNum; ++j) // ---- ⑤ { c1[j] = c2[j]; c2[j] = 0; } } cout << c1[nNum] << endl; } return 0; }
4.代码详解
我们需要把一个形如G(x)=(1+X^1+X^2+X^3+...)(1+X^2+X^4+X^6+...)....这样的函数
转换成形如F(x)=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)初始化F(x)= “G(x)的第一个括号中的内容” 代码中备注为①
2)将G(x)的第二个括号乘入F(x)中 [b]代码中备注为[/b]②
(1)将F(x)中第一项与G(x)中第二个括号的每一项相乘 [b][b]代码中备注为[/b][/b]③④
[b](2)将F(x)中第二项与G(x)中第二个括号的每一项相乘[/b]
[b] .....[/b]
[b] 3)[b]将G(x)的第三个括号乘入F(x)中[/b][/b]
[b][b] 4)[b]将G(x)的第四个括号乘入F(x)中[/b][/b][/b]
[b][b][b] ...[/b][/b][/b]
[b][b][b] 备注:[/b][/b][/b]
[b][b][b] 1) C1[i]中存的是 X^i的系数,C2[]为临时数组,用来保证C1[]的正确性。[/b][/b][/b]
[b][b][b] 2)根据题目给的物品重量的不同,初始化会不同,且后面的for()的累加也不同。[/b][/b][/b]
[b][b][b]5.相关练习[/b][/b][/b]
[b][b][b] [b][b][b][b]HDU1398 Square Coins[/b][/b][/b][/b][/b][/b][/b]
[b][b][b] HDU1028 Ignatius and the Princess III[/b][/b][/b]
[b][b][b] HDU1085 Holding Bin-Laden Captive![/b][/b][/b]
[b][b][b] HDU1171 Big Event in HDU[/b][/b][/b]
相关文章推荐
- 【算法小总结】母函数模板
- Linux学习总结—进程切换和调度算法深入分析
- 算法分析之分治法学习总结(一)
- QuickSort分析,这是回复提问时碰到的,顺便对学过的算法进行复习,总结...
- 算法总结系列之六: 桶排序(Bucket Sort)
- 算法总结系列之八:复读机的故事 - 散列表.NET应用的研究(下集)
- 算法总结系列之七:选择问题(Randomized Select)
- STL中的算法总结
- 算法总结系列之二: 快速排序(QuickSort)
- 算法总结系列之五: 基数排序(Radix Sort)
- 算法分析之分治法总结(二)
- 基于.NET 的 加密 解密 算法总结[一]
- 人脸检测算法总结
- 对Photoshop高斯模糊滤镜的算法总结
- 关于全文检索的归并的算法总结:
- 母函数算法---组合数学
- 表达式计算算法总结
- [★]基于.NET 的 加密 解密 算法总结[二]
- 表达式计算算法总结
- 算法总结系列之八:复读机的故事-散列表及其在.NET中的应用浅析(上集)