母函数入门

今天好像终于对困惑已久的母函数有了些感觉的样子….赶紧水一波.jpg


例一 骰子问题

掷两个清廉正直的骰子,点数之和为7的情况有多少?
我们来思考一下,嗯,7 = 1 + 6 = 2 + 5 = 3 + 4所以有6种。但是这样看上去一脸不爽的样子,所以我们不妨来搞一些事情。
f(x)=x+x2+x3+x4+x5+x6
那么
f(x)f(x)=x2+2x3+3x4+4x5+5x6+6x7+5x8+4x9+3x10+2x11+x12
好像很麻烦的样子,太不清真了。
但是倘若理性分析一波,就会神奇的发现,每一项系数对应的好像就是对应的方案数量。例如, x7 项系数对应是6,那么就有6种方法掷出来7。其实也很好理解啊,毕竟达到6这项就是通过和累加得来。
那么来思考一下:三个骰子掷出来和为10点的情况有多少?
仿照上面的方法,求一下 F(x)=f(n)3
得到这么一个式子:
x3+3x4+6x5+10x6+15x7+21x8+25x9+27x10+27x11+25x12+21x13+15x14+10x15+6x16+3x17+x18
当然是写代码复制粘贴.jpg
发现好像10前面的系数是27,所以应该有27种。

然后我们稍稍做个变形。现在有三个骰子,一个上面3个面写的是1、三个面写的是2,一个三个写的3、3个写的4,一个三个写的5、三个写的6,那么和是10的情况有多少种?(我们假定每个面是不同的)
我们对三个骰子分别建一个函数:
3x+3x2 3x3+3x4 3x5+3x6
那么
F(x)=(3x+3x2)(3x3+3x4)(3x5+3x6)=27x9+81x10+81x11+27x12
所以和为10有81种。
那么再来变形:如果骰子可以不投,仍然是3个,和为10的情况呢?
这就相当于我们加了一个 x0
F(x)=(1+x+x2)(1+x3+x4)(1+x5+x6)=1x0+3x1+3x2+3x3+12x4+21x5+21x6+18x7+18x8+45x9+90x10+81x11+27x12
足足有90种!
还可以自己玩,这里姑且放个代码

#include 
using namespace std;
int t1[] = {1, 3, 3, 0, 0, 0, 0};
int t2[] = {1, 0, 0, 3, 3, 0, 0};
int t3[] = {1, 0, 0, 0, 0, 3, 3};
int main() {
    int n = 6;
    for(int i = 0; i <= (n * 3); ++i) {
        int ans = 0;
        for(int j = 0; j <= n; ++j) {
            for(int k = 0; k <= n; ++k) {
                for(int l = 0; l <= n; ++l) {
                    if(t1[j] && t2[k] && t3[l])
                        if(j + k + l == i)
                            ans += t1[j] * t2[k] * t3[l];
                } 

            }
        }
        if(ans) cout<"·"<<"x^{"<"}+";
    }
} 

稍微总结一下,其实我们可以想到这样的一个结论:
母函数其实是加法原理和乘法原理的一种体现,加法原理体现在每一个小的决策的情况枚举,例如上面的变形中对于第一个骰子有七种决策:不投,3种投到1,3种投到2。
而对于三枚骰子,我们的事件是独立的,所以用乘法。
下面给出严格的数学定义:

设从 n 元集合 S={a1,a2,...,an} 中,限定元素 ai 出现次数集合为 Mi ,那么该集合的母函数为

F(x)=i=1n(mMixm)

例二 楼梯问题

n 块砖堆楼梯,要求:
1. 至少有两层
2. 每层楼梯数递增
3. 不能有两层楼梯数相同

这是一道经典的DP题,并且有各种状态设计。这里我们来用母函数解决。
考虑到选取第 i 块都有两种情况:选和不选,所以

F(x)=i=1n(1+xi)

那么现在我们就是要求解 F(x) 的第 n 项,事实上是个整数拆分问题的弱化版。
实现也很玄学:

ans[0] = ans[1] = 1;
for(int i = 2; i <= N; ++i)
    for(int j = N; j >= 0; --j)
        ans[i + j] += ans[j];
cout<1<

这里采用了顺推(刷表法)的手段,对于 i+j 的情况用 j 的情况来累加,这是由于。。好像不由于啥。
外层循环枚举拆分的第一个数,然后将剩余的值用已经推过的部分累加上去,而之所以内层要倒推的为了防止重复。而答案-1是因为这样统计会有一种一个台阶的情况,必须舍去。

例三 奇怪的数学题

六个数字,三个是1,两个是6,一个是8,能组成多少四位数?
顺着刚才的思路,可能你会写
F(x)=(1+x+x2+x3)(1+x+x2)(1+x)
然而并不是。
注意到这里某些不同选取会造成相同的结果,比如选取两个1。
所以我们给出指数形母函数:

F(x)=i=1n(mMixmm!)

乍一看比较懵,其实含义只是普通的除以一个排列数以去重而已。应用到上例中,
Ge(x)=(1+x+x22!+x33!)(1+x+x22!)(1+x)
=1+3x+8x22!+19x33!+38x44!+60x55!+60x66!
所以有38种。

简单的介绍了一些母函数的皮毛(毕竟我也没有完全理解orz),总的来说母函数是一种非常漂亮的解决计数问题的工具。

你可能感兴趣的:(数论)