母函数与排列组合

  在谈论母函数问题之前,我们先看一个简单的问题描述:假如有两组数据(A,B)和(C,D),每组中选出一个构成一个组合,总共有几种选法?很显然总共有4种选法:AC,AD,BC,BD。而且很容易联想到这个式子(A+B)*(C+D)=A*C+A*D+B*C+B*D。式子中的几个乘积项就是上面的4种选法。假如把问题换一下:每组中选出一个或0个数据构成组合,总共有几种组合?那么结果就变成:{空},A,B,C,D,AC,AD,BC,BD,而式子(1+A+B)*(1+C+D)=1+C+D+A+A*C+A*D+B+B*C+B*D,正好和上面组合的结果又一致(1代表什么都没选)。从这2个例子我们可以发现多项式乘积和组合存在着某种关系。事实上我们可以这么理解:(1+A+B)可以理解为从第一组数据中取0个数据,取A或者取B,同样(1+C+D)可以理解为从第二组数据取0个数据,取C或者取D。两者相乘的结果就表示了所有的组合。再看一下这个多项式:

  (1+x)*(1+x+x2)*(1+x3)=1+2x+2x2+2x3+2x4+2x5+x6

  这个多项式和上面的有一些区别了,它的幂级数超过1了。如果要从(1+x)、(1+x+x2)和(1+x3)中得到x的2次方的话,有两种选择:从(1+x)和(1+x+x2)中分别选择一个x或者从(1+x+x2)中选择x2;如果要得到x的6次方的话,只有1种选择,就是从(1+x)中选择x、(1+x+x2)中选择x2、(1+x3)中选择x3。也就是说乘积结果的每一项anxn的前面的系数an表示了从(1+x)、(1+x+x2)和(1+x3)中得到xn的组合数。

  其实上面的例子就利用了母函数的思想,下面来具体讨论一下母函数。

一.什么是母函数

  下面这个对于母函数的描述摘自维基百科:

  在数学中,某个序列 的母函数是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息。

  也就是说母函数是针对某个序列的,它的外在表现形式是一种形式幂级数。比如说有这样一个序列a0,a1,......an,构造一个函数

  f(x)=a0+a1x+a2x2+......+anxn

  则f(x)是序列a0,a1,......an的母函数。比如说最常见的(1+x)n,它是序列C(n,0),C(n,1),C(n,2)...C(n,n)的母函数。

  母函数包括几种,其中最常见的是普通型母函数和指数型母函数。普通型母函数是形如 f(x)=a0+a1x+a2x2+......+anxn的函数,而指数型母函数是形如G(x) = a0 + a1*(x)/1! + a2*(x2)/ 2! + a3*(x3)/3! + …… an*(xn)/k!的函数。

二.利用普通型母函数解决组合问题

 利用母函数的思想可以解决很多组合问题,下面举例说明:

 1.口袋中有白球2个,红球3个,黄球1个,从袋中摸出3个球有几种取法?

    和上面描述的例子类似,我们可以用次数代表球的个数,多项式的每一项前面的系数代表取法的种树。

  可以很容易地写出下面这个式子:

  (1+x+x2)(1+x+x2+x3)(1+x)

  (1+x+x2)表示有白球2个,1表示白球不取,x代表取1个白球,x2代表取2个白球,即用x的次数表示取球的个数,后面的也是类似。那么这个多项式的乘积就把所有的情况都表示出来了,对于最终乘积的每一项anxn,表示取n个球有an种取法。

2.有若干个1克,2克,5克的砝码,要称出20克的重量,有多少种称法?

  这里不限制砝码的个数,无所谓,照样写出母函数:

  (1+x+x2+x3+......xk+....)(1+x2+x4+x6......+x2n+......)(1+x5+x10+......x5m+......)

  因为要称出20克,所以只需要找找到结果中次数为20 的那一项就可以得到结果。

3.同样对于正数划分也可以解决,比如有整数20,划分成1,2,5,有多少种划分方法?

  解法和2的类似。

还有一类题目和这类似,有n个球放到m个盒子中,有多少种不同的放法?

(1+x+x2+x3+...xk+...)(1+x+x2+x3+...xk+...)(1+x+x2+x3+...xk+...)总共有m项,然后找出乘积中次数为n的那一项系数。

三.利用指数型母函数解决排列问题

  1.口袋中有白球2个,红球3个,黄球1个,任取3个作为一个排列,总共有多少种排列?

  类似地用指数型母函数解决

  用(1+x/1!+x2/2!)表示取白球0个,1个或者2个

  那么(1+x/1!+x2/2!)(1+x/1!+x2/2!+x3/3!)(1+x/1!)来表示所有的排列结果。

  =1+3x+4x2+19x3/6+19x4/12+6x5/12+x6/12

   =1+3*(x/1!)+8*(x2/2!)+19*(x3/3!)+38*(x4/4!)+60*(x5/5!)+60*(x6/6!)

  找到次数为3的那一项,系数为19,那么总共有19种排列。

  2.用1,2,3,4能够组成多少个5位数,要求1出现2次或者3次,2出现0次或者1次,3没有限制,4只出现偶数次。

  (x2/2!+x3/3!)(1+x)(1+x/1!+x2/2!+x3/3!+.....xk/k!+....)(1+x2/2!+x4/4!+......+x2n/(2n)!+......)

   每个式子的含义就不多解释了,读者应该能看懂它的含义。最终的结果就是x5/5!这一项的系数。

  用代码去实现母函数的计算过程很简单,它是模拟我们人工计算多项式乘积的过程,比如有多项式H1*H2*H3......

  我们先计算H1和H2的乘积,得到结果H',再用H'和H3相乘......依次类推下去,直到得到最终的结果。

//下面这道题目是航电上的一道题://题目意思是有1分,2分,5分的硬币各a,b,//c枚,求算不能组成的总钱数的最小值。
#include <iostream>
using namespace std;int main(int argc, char *argv[])
{int num[3];int cent[3]={1,2,5};          //次数增长步长 while(scanf("%d %d %d",&num[0],&num[1],&num[2]) != EOF){if(num[0]==0&&num[1]==0&&num[2]==0)break;int i,j,k;int c[8001],tempC[8001];     //因为三种硬币最多1000枚,1*1000+2*1000+5*1000=8000,那么多项式乘积的最高次数为8000 //c保存累计相乘各项的系数,tempC保存c和当前项相乘的系数 //c[i] 表示次数为i的那一项的系数int max=num[0]+2*num[1]+5*num[2];   //求出该组输入条件下的最高次数 for(i=0;i<=8001;i++)   {c[i]=0;tempC[i]=0;}//母函数为(1+x+x^2+...x^num[0])(1+x^2+x^4+....x^2*num[1])(1+x^5+x^10+...+x^5*num[2]) for(i=0;i<=cent[0]*num[0];i+=cent[0])   //第一个多项式的系数初始化 {c[i]=1;}for(i=1;i<3;i++)    //i表示总共有多少个多项式 {for(j=0;j<=max;j++)    //累计相乘的x^j的系数 {for(k=0;k+j<=max && k<=cent[i]*num[i];k+=cent[i])   //当前项x^k的系数 {tempC[k+j]+=c[j];   //x^j * x^k=x^(j+k)}}for(j=0;j<=max;j++)    //将临时数组清零 {c[j]=tempC[j];tempC[j]=0;}}for(i=0;i<=max;i++){if(c[i]==0)break;}printf("%d\n",i);}return 0;
}

母函数详解(转 侵删)相关推荐

  1. top命令参数详解_Linux、AIX的top命令各项指标详解(非原创侵删)

    一.Linux下监控服务器状态命令--top:各数据详解 top命令作用是实时现实服务器当前CPU.内存.负载.进程等信息 第一行 00:09:14 - 当前系统时间 1days, 13:14 - 系 ...

  2. mysqldump全量恢复_删库不跑路-详解MySQL数据恢复

    日常工作中,总会有因手抖.写错条件.写错表名.错连生产库造成的误删库表和数据的事情发生,那么,如果连数据都恢复不了,还要什么 DBA. 相关文章 MySQL备份策略:https://segmentfa ...

  3. 微信小程序系列(7)如何用微信小程序写一个论坛?贴心代码详解(五)删帖页【完结篇】

    源代码已开源,如果对你有帮助可以点个星:https://github.com/linkaimin/xdzs 写论坛不难,重点是各页面之间的信息传递! 先放成品图,虽然有点单调....但是麻雀虽小五脏俱 ...

  4. redis数据一致性之延时双删详解

    在使用redis时,需要保持redis和数据库数据的一致性,最流行的解决方案之一就是延时双删策略,今天我们就来详细刨析一下 注意:要知道经常修改的数据表不适合使用redis,因为双删策略执行的结果是把 ...

  5. 微信小程序php返回数组,微信小程序 数组(增,删,改,查)等操作实例详解...

    微信小程序 数组(增,删,改,查)等操作 最近在做一个小程序的demo.由于不向后台请求数据,所以就涉及到对本地数据的操作,也遇到了一些坑,本文就以数组的增删改查为例,给新手分享一些经验. 首先这是原 ...

  6. pandas 如何删掉第一行_pandas删除指定行详解

    pandas删除指定行详解 在处理pandas的DataFrame中,如果想像excel那样筛选,只要其中的某一行或者几行,可以使用isin()方法来实现,只需要将需要的行值以列表方式传入即可,还可传 ...

  7. 不带头节点的链表有哪些缺点_23张图!万字详解「链表」,从小白到大佬!

    链表和数组是数据类型中两个重要又常用的基础数据类型. 数组是连续存储在内存中的数据结构,因此它的优势是可以通过下标迅速的找到元素的位置,而它的缺点则是在插入和删除元素时会导致大量元素的被迫移动,为了解 ...

  8. linux tf命令,Linux系统命令介绍之vmstat命令详解

    今天小编要跟大家介绍的vmstat命令详解.熟悉Linux系统和使用Linux系统工作的小伙伴都知道Linux的命令有很多,而真正在工作中用到的命令应该不超过几十个,为了让大家更好的掌握这些命令,小编 ...

  9. EEG伪影详解和过滤工具的汇总(二)

    点击上面"脑机接口社区"关注我们 更多技术干货第一时间送达 在<EEG伪影类型详解和过滤工具的汇总(一)>,我们详细介绍了EEG伪影类型和产生原因,这篇文章,我们主要介 ...

最新文章

  1. 沦为一个教师——地震余震篇
  2. Js获取地址栏参数值
  3. 依赖项出现感叹号怎么办_SpringBoot中如何对依赖进行管理?
  4. 协程是什么?怎么来的?它有什么作用?
  5. 《中国大学--博弈论》
  6. 一个完整的person类
  7. JS遍历map集合以及map对象
  8. 可以联机的的单机游戏
  9. 步进电机、伺服电机、舵机的原理和区别
  10. IDEA导入已有Maven项目
  11. TortoiseSVN安装及导入已有SVN仓库
  12. ffmpeg与x264编码指南
  13. 混淆矩阵 python实现
  14. 基于matlab的电机,基于MATLAB的电机仿真研究
  15. coreldraw 导入面料_CorelDRAW 导入和导出文件
  16. 华为安卓手机记事本内容导出
  17. Java基础 之 lambda、stream概念及实际使用举例
  18. 青龙面板京东羊毛最新拉库(目前在维护的脚本更新)
  19. 扫码排号测试用例_测试用例:水杯、电梯、发红包、朋友圈点赞、支付的测试用例等等...
  20. W25Q256被写保护如何修改

热门文章

  1. Oauth2 resource server入门配置
  2. [GEF循序渐进系列之二]GEF概述
  3. java基础多线程抢红包_Java实现抢红包功能
  4. 一种可以原地旋转并能自由升降的手推车
  5. python机器语言直接用二进制代码表达指令_什么是一种二进制语言,它直接使用二进制代码表达指令?...
  6. html的 转义,html字符转义
  7. 能否将上述几点方法举例并进行内容润色?
  8. 最强旅游攻略 | 用Python分析国庆中秋最佳旅游景点 (文末福利)
  9. CSS设置文字镂空效果
  10. 《延禧攻略》网播50亿+,脑洞广告背后有家智能营销扫地僧