对于母函数,我第一次见还是在HDU2082上见到的,感觉是个很nb的思想,因为运用到了离散数学的知识,所以我在这里简单的介绍一下吧。
从一个比较经典的例子入手:
题目:有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?
因为每个砝码只有一种一枚,所以一般而言一共24种(即对于每个砝码而言称与不称),倘若是n个砝码,则是2n种。当然啦这太容易理解了。
但问题不会这么简单,所以!对于普通母函数——把组合问题的加法法则和幂级数的的乘幂的相加对应起来,这句话可能一开始难以理解,不过其实学完了之后很容易理解,母函数的思想很简单—就是把离散数列和幂级数一一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造。
我们需要用到幂级数运算的知识了:
假设1g的砝码,放的话是x1,不放的话是x0;2g的话,放的是x2,不放是x0;4g放的话是x4,不放是x0依次类推,注意这里应该是幂次方的关系,为了后面能加。所以我们再把题目化简:只有1g和2g两个砝码,能有几个放法?
解答:(x0+x1)(x0+x2)=x0+x1+x2+x3;
那么如果是一开始的题目嘞?
解答:(x0+x1)* (x0+x2) * (x0+x3)* (x0+x4)
=x0 + x1 + x2 + 2x3 + 2x4 + 2x5 + 2x6 + 2x7 + x8+ x9 + x10
注意,x前面是序数。
那么问题就迎刃而解了。一共有10种结果,16种组合法。
那么接下来,再加深一步,如果是每个硬币无穷个呢,硬币分别为1、2、3、4…直到无穷。
当然啦,还是运用到幂级数运算的想法了。当然一般会有个限定,那我限定硬币到5吧
那就是(x0+x1+x2+x3+x4+x5)(x0+x2+x4)(x0+x3)(x0+x4)(x0+x5)
很好理解吧!
展示一下代码:
#include<iostream>
#include<cmath>
#include<string>
#include<string.h>
#include<set>
#include<stdio.h>
#include<algorithm>
using namespace std;
int sup[1000],temp[1000];
int main()
{
int target;
int i,j,k;
while(cin>>target){//输入希望得到的目标硬币和
for(i=0;i<=target;i++){
sup[i]=1;
temp[i]=0;
}
for(i=2;i<=target;i++){
for(j=0;j<=target;j++){
for(k=0;k+j<=target;k+=i){
temp[j+k]+=sup[j];
}
}
for(j=0;j<=target;j++){
sup[j]=temp[j];
temp[j]=0;
}
}
cout<<sup[target]<<endl;
}
}
详情可以参考:https://blog.youkuaiyun.com/yu121380/article/details/79914529