母函数入门

例子:若有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?各有几种可能方案?       

如何解决这个问题呢?考虑构造母函数。
如果用x的指数表示称出的重量,则:
    1个1克的砝码可以用函数1+x表示,
    1个2克的砝码可以用函数1+x2表示,
    1个3克的砝码可以用函数1+x3表示,
    1个4克的砝码可以用函数1+x4表示

(1+x)(1+x2)(1+x3)(1+x4)
=(1+x+x2+x3)(1+x3+x4+x7)
=1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10 
从上面的函数知道:可称出从1克到10克,系数便是方案数。
    例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1;同样,6=1+2+3=4+2;10=1+2+3+4。
    故称出6克的方案有2,称出10克的方案有1

砝码称重量,贴邮票,数字拆分 等问题都为母函数问题

练习:牢牢把握x的指数表示称出的重量

1.若有1克砝码3枚、2克砝码4枚、4克砝码2枚,问能称出哪几种重量?各有几种方案?

(1+x+x2+x3)(1+x2+x4+x6+x8)(1+x4+x8)

2.整数n拆分成1,2,3,…,m的和,求其母函数。

(1+x+x2+x3+...)(1+x2+x4+x6+...) (1+x3+x6+...)...(1+xm+x2m+x3m+...)

3.如若上例中m至少出现一次,其母函数又如何?

(1+x+x2+x3+...)(1+x2+x4+x6+...) (1+x3+x6+...)...(xm+x2m+x3m+...)


如果计算(1+x+x2+x3+...)(1+x2+x4+x6+x8+...)(1+x4+x8+...) ...(1+xN+x2N+x3N+...)?

//以下是模板

       //c1表示每次计算出来的多项式系数,

      //c2表示临时的结果多项式的系数

     // 因此c1,c2定界时,要考虑到c1,c2最大能表示多少

        //初始化

        //初始化的是第一个多项式的系数

        for(int i=0;i<=n;i++){
            c1[i]=0;
            c2[i]=0;
        }
        //c2的系数一定为0
        //但是c1的系数不一定为0,有可能是1+x^2+x^4+x^6+x^8+...
        //c1系数为1,0,1,0,1,0,1,0,1 ...
        //所以初始化要注意
        for(int i=0;i<=n;i++){
            c1[i]=1;

        }

        //进行计算时,是先将相邻的括号合并,合并组成新括号,与下一个相邻的括号合并,这样的操作进行n-1次

        //而将二个括号合并为一个时候,进行的是指数的乘法,用加法表示结果,即同底数幂相乘,底数不变指数相加,所以是c2[j+k]+=c1[j]*c1[k]

             

        //i是控制趟数,表示n个括号变为1个括号,要列出母函数,看清楚到底有多少个括号

        //进行n-1次变换,n-2+1
        //i设置为2,同时还表示每个括号里x的次数最开始为i

        for(int i=2;i<=n;i++){


            //j和k循环表示计算2个括号合并的过程

            //j控制第1个括号,k控制第2个括号 ,合并过程中分别表示第1,2个括号有多少项

            //合并过程中,k存在跳项的可能性,即k可能为k+=某数字

            //而j是不可能跳项的,因为在合并过程中,j控制前一个括号的中的项数,每次合并完2个括号,会有新的项数,因此一定要逐项扫描,即j++

            for(int j=0;j<=n;j++){


                //j+k<=n控制k的次数,使得结果即c2[j+k]最多为n
                //k+=i,
                //每个括号里x的次数是2,4,6,8或着3,6,9或者4,8,16
                //k+=i是循环上面的序列 2,4,6,8或着3,6,9或者4,8,16
                //所以i是关键,是2,3,4,5...,所以上面才设置i为2
                //但是有时系列不一定是2,3,4...
                //有可能是2,9,14,23,43543 一些无规律的数字

                //因此也可以用数组来表示这些数字


                for(int k=0;k+j<=n;k+=i){


                    //注意是+=因为要循环好多次
                    // c2[j+k]+=c1[j]等价于c2[j+k]+=c1[j]*c2[k];

                    //因为后者是没有计算过的,系数都是1


                    c2[j+k] +=c1[j];
                }
            }
          

            for(int j=0;j<=n;i++){

                 //将结果临时结果赋给c1

                c1[i]=c2[i];


                //c2重新初始化
                 c2[i]=0;

            }

最后一句话:c[i]存储的数字表示是构成i的方法数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值