算法总结之母函数

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博客

 1 #include <iostream>
 2 using namespace std;
 3 // Author: Tanky Woo
 4 // www.wutianqi.com
 5 const int _max = 10001;
 6 // c1是保存各项质量砝码可以组合的数目
 7 // c2是中间量,保存没一次的情况
 8 int c1[_max], c2[_max];
 9 int main()
10 {    //int n,i,j,k;
11     int nNum;   //
12     int i, j, k;
13
14     while(cin >> nNum)
15     {
16         for(i=0; i<=nNum; ++i)   // ---- ①
17         {
18             c1[i] = 1;
19             c2[i] = 0;
20         }
21         for(i=2; i<=nNum; ++i)   // ----- ②
22         {
23
24             for(j=0; j<=nNum; ++j)   // ----- ③
25                 for(k=0; k+j<=nNum; k+=i)  // ---- ④
26                 {
27                     c2[j+k] += c1[j];
28                 }
29             for(j=0; j<=nNum; ++j)     // ---- ⑤
30             {
31                 c1[j] = c2[j];
32                 c2[j] = 0;
33             }
34         }
35         cout << c1[nNum] << endl;
36     }
37     return 0;
38 }

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)中  代码中备注为

         (1)将F(x)中第一项与G(x)中第二个括号的每一项相乘 代码中备注为③④

         (2)将F(x)中第二项与G(x)中第二个括号的每一项相乘

         .....

      3)将G(x)的第三个括号乘入F(x)中

      4)将G(x)的第四个括号乘入F(x)中

      ...

    备注:

      1) C1[i]中存的是 X^i的系数,C2[]为临时数组,用来保证C1[]的正确性。

      2)根据题目给的物品重量的不同,初始化会不同,且后面的for()的累加也不同。

5.相关练习

    HDU1398 Square Coins

    HDU1028 Ignatius and the Princess III

    HDU1085 Holding Bin-Laden Captive!

    HDU1171 Big Event in HDU

算法总结之母函数

时间: 2024-08-09 02:06:49

算法总结之母函数的相关文章

母函数及相关的算法题

母函数即生成函数,构造这么一个多项式函数g(x),使得x的n次方系数为f(n),是组合数学中尤其是计数方面的一个重要理论和工具. (1+a1x)(1+a2x)(1+a3x)...(1+anx)=1+(a1+a2+a3+...+an)x+(a1a2+a1a3+...+an-1an)x2+...+(a1a2a3*...*an)xn 由此可以看出: 1. x的系数是a1,a2,…an的单个组合的全体.相当于从a1,a2,…an选1个进行组合,然后加在一起 2. x2的系数是a1,a2,…an的两个组合

hdu2082 找单词 母函数+完全背包两种算法AC。。数据较水

找单词 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4615    Accepted Submission(s): 3304 Problem Description 假设有x1个字母A, x2个字母B,..... x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,..... 字母Z的价值为26.那么,对于给定的字母,可以找

acm常见算法及例题

转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推.     (5)构造法.(poj3295)     (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法

ACM算法总结及刷题参考

参考:http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信)(poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期: 一.基本算法: (1)枚举. (poj1753,poj2965)    (2)贪心(poj1328,poj2109,poj2586)    (3)递归和分治法.     (4)递推.     (5)构造法.(po

转:转一个搞ACM需要的掌握的算法. .

要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.  适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红,  发挥自己的长处,这才是重要的. 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,  因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打  出来.  1.最短路(Floyd.Dijstra,BellmanFord)  2.最小生成树(先写个prim,kruscal要用并查集,不好写)

STL六大组件之——算法小小小小的解析

参考自侯捷的<stl源码剖析> stl算法主要分为非可变序列算法(指不直接修改其所操作的容器内容的算法),可变序列算法(指可以修改它们所操作的容器内容的算法),排序算法(包括对序列进行排序和合并的算法.搜索算法以及有序序列上的集合操作),数值算法(对容器内容进行数值计算). 1.非可变序列算法 stl中的非可变序列算法有:for_each(), find(), find_if(), adjacent_find(), find_first_of(), count(), count_if(), m

【ACM算法纲要】【转自ALPC】

基本 C/C++.STL(vector.set.map.queue.string.algorithm) 枚举.贪心.递归.分治.递推.模拟 构造.位运算.常数优化 数据结构 队列.堆.栈.链表 排序(插入.冒泡.快速.归并.堆.桶.基数) 二分查找.散列表.并查集.哈夫曼树 排序二叉树.左偏树.平衡树(Splay/Treap/SBT) 树状数组.线段树.归并树.划分树.主席树.树套树 树链剖分.动态树 1/2维RMQ.LCA(在线/离线).稀疏表.字典树 字符串 KMP.扩展KMP AC自动机

算法初学者指南

摘自网络,对于这个训练计划,我只能膜拜,~ 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码, 因为太常用,所以要练到写时不用想,10-15 分钟内打完,甚至关掉显示器都可以把程序打 出来. 1.最短路(Floyd.Dijstra,BellmanFord) 2. 最小生成树(先写个prim,kruscal要用并查集,不好写) 3.大数(高精度)加减乘除 4.二分查找. (代码可在五行以内) 5.叉乘.判线段相交.然后写个凸包. 6.BFS.DFS,同时熟练hash表(

常见算法和例题

第3章  算法与程序设计模块 3.1  算    法 算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作. 常用的算法:列举了穷举搜索.递归.回溯.递推.模拟.分治.贪心.深度优先搜索.广度优先搜索等几种较为常用的算法,没有做过多的描述,一旦给出具体描述,容易使内容加深,产生严重学科取向的引导,符合教育部普通高中课程方案的特点,对于这些必需的方法和思想,关键不在于学生能不能,而在于教师是否想到,是否有过关注,引发学生对系统方法和思想的思考,重视建立编程思想,