例子:若有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个括号,要列出母函数,看清楚到底有多少个括号
//i设置为2,同时还表示每个括号里x的次数最开始为i
for(int i=2;i<=n;i++){
//j控制第1个括号,k控制第2个括号 ,合并过程中分别表示第1,2个括号有多少项
//合并过程中,k存在跳项的可能性,即k可能为k+=某数字
//而j是不可能跳项的,因为在合并过程中,j控制前一个括号的中的项数,每次合并完2个括号,会有新的项数,因此一定要逐项扫描,即j++
for(int j=0;j<=n;j++){
//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
}
}
for(int j=0;j<=n;i++){
//将结果临时结果赋给c1
c1[i]=c2[i];
c2[i]=0;
}
最后一句话:c[i]存储的数字表示是构成i的方法数!