母函数(数学问题)

生成函数即 母函数,是组合数学中尤其是计数方面的一个重要理论和工具。

生成函数有普通型生成函数和指数型生成函数两种,其中普通型用的比较多。形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题。

普通型母函数

定义:
对于任意数列a0,a1,a2...an 即用如下方法与一个函数联系起来:
G(x) = a0 + a1x + a2x*2 + a3x^3 +....+ anx^n
则称G(x)是数列的 生成函数(generating function)
例子:
比较典型的是:A(x) = (1+x)^n~C(n,0),C(n,1),C(n,2),C(n,3),.....,C(n,n)
C(n,0),C(n,1),C(n,2),C(n,3),.....,C(n,n)是x^0,x^1....x^n的系数

指数型母函数:

生成函数是说,构造这么一个多项式函数g(x),使得x的n次方系数为f(n)。 如:序列{0,1,2,3,4,5...n}的 生成函数为:f(x)=0+x+2x^2+3x^3+4x^4+...+nx^n
生成函数最绝妙的是,某些生成函数可以 化简为一个很简单的函数。也就是说,不一定每个 生成函数都是用一长串多项式来表示的。比如,这个函数f(n)=1 (n当然是属于自然数的),它的 生成函数就应该是g(x)=1+x+x^2+x^3+x^4+...(每一项都是一,即使n=0时也有x^0 系数为1,所以有 常数项)。再仔细一看,这就是一个有无穷多项的 等比数列求和嘛。如果-1<x<1,那么g(x)就等于1/(1-x)了。在研究 生成函数时,我们都假设级数收敛,因为生成函数的x没有实际意义,我们可以任意取值。于是,我们就说,f(n)=1的 生成函数是g(x)=1/(1-x)。
我们举一个例子说明,一些具有实际意义的组合问题也可以用像这样简单的一个函数全部表示出来。
考虑这个问题:从只有4个MM的二班选n个MM出来有多少种选法。学过简单的排列与组合的同学都知道,答案就是C(4,n)。也就是说。从n=0开始,问题的答案分别是1,4,6,4,1,0,0,0,...(从4个MM中选出4个以上的人来方案数当然为0喽)。那么它的 生成函数g(x)就应该是g(x)=1+4x+6x^2+4x^3+x^4。这不就是…… 二项式展开吗?于是,g(x)=(1+x)^4。
你或许应该知道,(1+x)^k=C(k,0)x^0+C(k,1)x^1+...+C(k,k)x^k;但你或许不知道,即使k为 负数和小数的时候,也有类似的结论:(1+x)^k=C(k,0)x^0+C(k,1)x^1+...+C(k,k)x^k+C(k,k+1)x^(k+1)+C(k,k+2)x^(k+2)+...(一直加到无穷;式子看着很别扭,自己写到草稿纸上吧,毕竟这里输入 数学式子很麻烦)。其中,广义的组合数C(k,i)就等于k(k-1)(k-2)…(k-i+1)/i!,比如C(4,6)=4*3*2*1*0*(-1)/6!=0,再比如C(-1.4,2)=(-1.4)*(-2.4)/2!=1.68。后面这个就叫做 牛顿二项式定理。当k为整数时,所有i>k时的C(k,i)中分子都要“越过”0这一项,因此后面C(k,k+1),C(k,k+2)之类的都为0了,与我们的经典二项式定理结论相同;不同的是, 牛顿二项式定理中的指数k可以是任意 实数
我们再举一个例子说明一些更复杂的 生成函数。n=x1+x2+x3+...+xk有多少个 非负整数解?这道题是学排列与组合的经典例题了。把每组解的每个数都加1,就变成n+k=x1+x2+x3+...+xk的 正整数解的个数了。教材上或许会出现这么一个难听的名字叫“ 隔板法”:把n+k个东西排成一排,在n+k-1个空格中插入k-1个“隔板”。答案我们总是知道的,就是C(n+k-1,k-1)。它就等于C(n+k-1,n)。它关于n的 生成函数是g(x)=1/(1-x)^k。这个 生成函数是怎么来的呢?其实,它就是(1-x)的-k次方。把(1-x)^(-k)按照刚才的牛顿 二项式展开,我们就得到了x^n的系数恰好是C(n+k-1,n),因为C(-k,n)*(-x)^n=[(-1)^n*C(n+k-1,n)]*[(-1)^n*x^n]=C(n+k-1,n)x^n。这里看晕了不要紧,后文有另一种方法可以推导出一模一样的公式。事实上,我们有一个纯组合数学的更简单的 解释方法。因为我们刚才的 几何级数1+x+x^2+x^3+x^4+...=1/(1-x),那么(1+x+x^2+x^3+x^4+...)^k就等于1/(1-x)^k。仔细想想k个(1+x+x^2+x^3+x^4+...)相乘是什么意思。(1+x+x^2+x^3+x^4+...)^k的展开式中,n次项的系数就是我们的答案,因为它的这个系数是由原式完全展开后k个指数加起来恰好等于n的项合并起来得到的。
题目一:

我们要从苹果、香蕉、橘子和梨中拿一些水果出来,要求苹果只能拿偶数个,香蕉的个数要是5的倍数,橘子最多拿4个,梨要么不拿,要么只能拿一个。问按这样的要求拿n个水果的方案数。
结合刚才的k个(1+x+x^2+x^3+x^4+...)相乘,我们也可以算出这个问题的 生成函数
引用内容
g(x)=(1+x^2+x^4+...)(1+x^5+x^10+..)(1+x+x^2+x^3+x^4)(1+x)
=[1/(1-x^2)]*[1/(1-x^5)]*[(1-x^5)/(1-x)]*(1+x) (前两个分别是 公比为2和5的几何级数,
第三个嘛,(1+x+x^2+x^3+x^4)*(1-x)不就是1-x^5了吗)
=1/(1-x)^2 ( 约分,把一大半都约掉了)
=(1-x)^(-2)=C(1,0)+C(2,1)x+C(3,2)x^2+C(4,3)x^3... (参见刚才对1/(1-x)^k的展开)
=1+2x+3x^2+4x^3+5x^4+....
于是,拿n个水果有n+1种方法。我们利用 生成函数,完全使用代数手段得到了答案!

题目二:

我有1分、2分和5分面值的硬币。请问凑出n分钱有多少种方法。想一下刚才的水果,我们不难得到这个问题的生成函数:g(x)=(1+x+x^2+x^3+...)(1+x^2+x^4+...)(1+x^5+x^10+..)=1/[(1-x)(1-x^2)(1-x^5)]

说明:1+x+x^2+x^3+...是将一份硬币出现的所有情况列出来, x的次方代表硬币的面值

母函数(Generating function)详解

“母函数的思想很简单—就是把离散 数列幂级数一一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “

我们首先来看下这个多项式 乘法: (以下图片都可以点击放大)
母函数详解

  母函数详解

由此可以看出:
1.x的系数是a1,a2,…an 的单个组合的全体。
2. x2的系数是a1,a2,…a2的两个组合的全体。
………
n. xn的系数是a1,a2,….an的n个组合的全体(只有1个)。
由此得到:如有图
母函数详解

  母函数详解

母函数的定义:
对于序列a0,a1,a2,…构造一函数:
母函数详解

  母函数详解

图三
称函数G(x)是序列a0,a1,a2,…的母函数

这里先给出2个例子,等会再结合题目分析:第一种:
有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
考虑用母函数来解决这个问题:
我们假设x表示砝码,x的指数表示砝码的重量,这样:
1个1克的砝码可以用函数1+x表示,
1个2克的砝码可以用函数1+x∧2表示,
1个3克的砝码可以用函数1+x∧3表示,
1个4克的砝码可以用函数1+x∧4表示,
上面这四个式子懂吗?
我们拿1+x^2来说,前面已经说过,x表示砝码,x的指数表示砝码的重量!即这里就是一个质量为2的砝码,那么前面的 1表示什么?按照上面的理解,1其实应该写为:1*x^0,即1代表重量为2的砝码数量为0个。(理解!)
不知道大家理解没,我们这里结合前面那句话:
把组合问题的加法法则和幂级数的t的乘幂的相加对应起来
1+x^2表示了两种情况:1表示质量为2的砝码取0个的情况,x表示质量为2的砝码取1个的情况。这里说下各项系数的意义:
在x前面的系数a表示相应质量的砝码取a个,而1就表示相应砝码取0个,这里可不能简单的认为相应砝码取0个就该是0*x(想下为何?结合 数学式子)。
所以,前面说的那句话的意义大家可以理解了吧?几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:
(1+x)(1+x∧2)(1+x∧3)(1+x∧4)
= (1+x+x^2+x^3)(1+x^3+x^4+x^7)
=1+x+x^2+2x^3+2x^4+2x^5+2x^6+2x^7+x^8+x^9+x^10
从上面的函数知道: 可称出从1克到10克,系数便是方案数。(!!!经典!!!)
例如右端有2x项,即称出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分的邮票贴出不同数值的方案数:
大家把这种情况和第一种比较有何区别?第一种每种是一个,而这里每种是无限的。求
一个数值的组成方法有几种?

母函数详解

  母函数详解

以展开后的x为例,其系数为4,即4拆分成1、2、3之和的拆分数为4;
即 :4=1+1+1+1=1+1+2=1+3=2+2
这里再引出两个概念整数拆分和拆分数:
所谓 整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。
整数拆分成若干整数的和,办法不一,不同拆分法的总数叫做 拆分数
现在以上面的第二种情况每种种类个数无限为例,给出 模板


import java.util.Scanner;

/*功能:利用母函数求求用1分、2分、3分的邮票贴出不同数值的方案数:这里每种邮票是无限的。求
一个数值的组成方法有几种?
 * */
public class MuHanShu {

    private static int max=10000;
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();//数值
        
        int[] c1=new int[max];//保存最终的所有结果(x次幂的系数,下标代表次幂,元素代表系数)
        int[] c2=new int[max];//质数一个临时的数组,保存临时的结果值
        
        while(n!=0)//以0为输入的结束标志
        {
            //得到一个n值之后,首先要将上一次的两个数组中的值清空,初始化为0
            for(int i=0;i<=n;i++)//因为要求的是x的n次幂的系数,数组的下标代表次幂,元素
                                 //代表系数,所以数组下标大于n的没必要保存,也不需要知道
            {
                c1[i]=0;
                c2[i]=0;
            }
            
            /*因为下面的程序是首先拿第一个多项式(数组c1保存第一个多项式的各项的系数)和第二
             * 个多项式相乘,结果首先保存到数组c2中,然后再将结果赋值给数组c1,所以数组c1保存的
             * 是第一个多项式的系数,和以后前面多项式相乘的结果,所以根据该题,第一个多项式
             * 的系数全是1,所以下面要将初始值初始化为1*/
            for(int i=0;i<=n;i++)//小于等于n 的原因同上
            {
                c1[i]=1;
            }
            
            //下面的代码实现多个多项式相乘并将结果保存在数组c1中
            for(int i=2;i<=n;i++)//i代表的是当前求得是第i个多项式和前面所有多项式的积再乘积
            /*i要小于n的原因是,在该题中第n项多项式的第二项是x^n,要求的是x^n的系数,所以,第n+1
             * 个多项式的除了x^0这样之外的任意一项和别的书相乘的结果的x 的次幂肯定会大于n,但是x^0
             * 这一项代表的是没有取,多以孩只要乘到第n个多项式就好了*/
            {
                /*下面实现第i个多项式与前面i-1个多项式的乘积的乘积*/
                for(int j=0;j<=n;j++)//小于等于n 的原因同上
                //j代表的是前面i-1个多项式的乘积的每一项的x的次幂
                {
                    for(int k=0;k+j<=n;k+=i)//k代表的是第i个多项式的每一项的x的次幂
                    {
                        c2[k+j]+=c1[j];
                    }
                }
                
                //下面实现第i个多项式与前面i-1个多项式的乘积的乘积的结果赋给数组c1
                for(int j=0;j<=n;j++)//小于等于n 的原因同上
                {
                    c1[j]=c2[j];
                    c2[j]=0;//记得数组c2 每次都要清空,否则出现错误
                }
            }
            //输出想要的值
            System.out.println(c1[n]);
            n=sc.nextInt();
            
        }
    }

}

说明:上面程序不只是只有三个多项式相乘,当输入的数值为几就会有几个多项式相乘,第几个多项式就代表邮票的面值是几,如果只想要3个多项式相乘的话,那么就把
              程序中,下面这句
             for(int i=2;i<=n;i++)//i代表的是当前求得是第i个多项式和前面所有多项式的积再乘积
            中的n换成3即可


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值