母函数入门

母函数入门

问题引入

  • 假设我们当前有质量分别为 1g, 2g, 3g, 4g 的砝码各一个, 我们可以构造出多少种质量为7g的砝码方案?

基础解法

  • 显然, 想要指定重量的砝码序列的构造, 对于每一个砝码, 我们都有使用或者不使用两种选择. 如果我们对每个砝码进行枚举的话, 则共需要枚举 24 种选择, 即这种解法的时间复杂度为 O(2n) .

代数解法

  • 我们定义变量 x 代表砝码, x 的次幂代表砝码的质量. 例如 x4 就代表当前砝码的质量为 4g. 那么由选择或者不选择当前砝码, 我们可以将其写为表达式 : (1x0+1x4) , x0 代表我们不选择当前砝码进行构造, x4 代表我们选择当前砝码进行构造.
  • 那么我们就可以将对砝码的序列构造成一序列表达式的乘积, 即 (1+x)(1+x2)(1+x3)(1+x4)
  • 我们展开这个表达式, 可以得到 1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10
  • 由我们的定义可知, 幂函数对应的系数即为构造某个砝码重量的方案数.例如 x7 的系数为 2, 那么我们有两种方案, 即 7 = 1 + 2 + 3 = 3 + 4

母函数定义

  • 将一个离散序列对一个幂函数序列对应起来, 构造一个新的离散数列.
  • 即给定离散序列 a0,a1,,an 和 幂函数序列 x0,x1,,xn , 我们构造出一个函数:
    G(n)=a0x0++anxn=iaixi

    • 我们称函数 G(x) 为 序列 a0,a1,,an 的母函数

联系

  • 那么母函数与我们的方法有什么联系呢? 我们来看一下一系列的一元线性函数的相乘结果 :
  • (1+a1x)(1+a2x)(1+anx)=1+(a1+a2++an)x++(a1a2+a1a3++an1an)x2++a1a2anxn
  • 显然, 一系列一元一次函数的乘积可以被简化为母函数的形式. 易知, 我们可以将一元一次函数推广到一元多次函数, 这里不再赘述.

问题解决

  • 接下来, 我们来解决一个问题, 求用 1 分, 2分, 3分的邮票贴出不同数值的方案数.
  • 了解了代数解法中 (1+x4) 的意义, 那么我们就可以写出当前问题的母函数 G(x)
    G(x)=(1+x+x2++xn)(1+x2+x4++x2n)(1+x3+x6++x3n)
  • 显然, 对这个式子进行计算, 那么得到的 xn 前的系数就是邮票价值为 n <script type="math/tex" id="MathJax-Element-40">n</script>时的组成方案数.

代码

"""
    1. 计算给定最大价值邮票数额, 计算出小于给定价值的邮票的组成方案数的集合.
    2. 我们不保存幂函数的次幂, 只保存幂函数的系数. 因为次幂可以通过下标的枚举来控制.
"""


def generating_func(value):
    value += 1  # 我们在数组中需要使用到价值为 value的组成方案数, 故需要防止溢出
    count = [1] * value  # 由表达式可知, 第一个表达式的每一个幂函数的系数都为 1
    temp = [0] * value  # 存储中间结果
    for expression_index in range(2, value):  # 只需要计算第二个表达式以及之后的表达式
        for item_index in range(0, value):  # 枚举当前表达式所有幂函数的系数
            for mul_item_index in range(0, value, expression_index): # 枚举相乘的表达式的幂函数的所有系数
                if item_index + mul_item_index < value:
                    temp[mul_item_index + item_index] += count[item_index]  # 更新对应次幂的系数值
        count = temp.copy()  # 保存计算完前 expression_index 个表达式的计算结果.
        temp = [0] * value
    return count

其他应用

  • 我们对于指定邮票数额的构造可以看做一系列一定数量的一些邮票数额的加法, 反过来看, 那么其也可以对应成整数的拆分, 例如 7 = 1 + 2 + 4. 所以幂函数的系数也可以看做整数的拆分数.

总结

  • 本文介绍的方法只适用于母函数的入门, 如果还需要深入学习, 需要点击下面的链接, 有更多的资料可以学习.

参考文献

母函数详解
母函数入门

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值