初学者的母函数理解

今天通过大佬们的文章,初步对母函数有了一定的了解。下面是我比较具体的看了这位大佬的文章,总结的我自己的了解情况,可能不是很完美,但也算是一个进步,记录一下,以便于以后我回忆巩固。
首先,我们通过一个例题来思考母函数。
例1:有1g 2g 3g 4g的砝码各一枚,可以称出哪几种重量?每种重量各有几种方案?
如果
(使用1g||不使用1g)&&(使用2g||不使用2g)
=使用1g&&使用2g || 不使用1g&&使用2g || 使用1g&&不使用2g || 不使用1g&&不使用2g
每个用 “||”分开的一项都是一种方案。“&&”表示选择第一项的情况下有选择了第二项。
这样如果把“||”看做加法,"&&"看做乘法,那么就和多项式的乘法一样了。那么,我们就可以通过多项式乘法来表示组合情况。通过一种运算,用乘法的形式运算但结果类似有加法,这让我们联想到了幂运算。Xm×Xn=Xm+n符合了我们的要求。那么我们就可以用aXb来表示,其中a表示方案的个数,b表示砝码组合的重量。
1g=X0+X1 (0表示没有使用砝码,所以重量为0)
2g=X0+X2
3g=X0+X3
4g=X0+X4
4个砝码的组合情况:
(X0+X1)×(X0+X2)×(X0+X3)×(X0+X4)=X0+X1+X2+2X3+2X4+2X5+2X6+2X7+X8+X9+X10
(这里可以自己计算得到)
因为次数代表组合后可以称出的重量,系数代表组合出这种质量的方案的数量,因此可以得知,1g 2g 8g 9g 10g的方法有1种,3g 4g 5g 6g 7g的组合方法有2种。

如果把题目稍加修改,用1g 2g 3g的砝码称出不同重量的方案。这时候的题目和之前的题目相比,前一题是每种一个而这里是每种无限个。
那么,我们如何来体现“无限个”这个概念呢?很简单,我们可以拿2g的砝码举个栗子,因为我们有无限个2g的砝码,所以我们可以把2个2g的砝码当做4g的砝码,3个2g的砝码当做6g的砝码,以此类推,把m个n g砝码当做m*n砝码,那么如果只有1g和2g的砝码,我们的多项式就可以列成:
(x0+x1+x2+x3+x4+x5+ …… )×(x0+x2+x4+x6+x8+x10+ ……)
由于实际问题中,对于所组成的砝码重量一定有一个确定的值,比如10g,所以,我们只要再合并后的结果求到最高次项是10即可,后面的项可以忽略不计。
那么如果题目给出的是1g 2g 3g的砝码称出10g的方案,表达式就是:
(x0+x1+x2+x3+x4+x5+ …… +x10)×(x0+x2+x4+x6+x8+x10)×(x0+x3+x6+x9
结果就是合并同类项后X10的系数。
那么知道了它的原理,用C语言实现输出无限砝码情况下的某种重量的方案如下:

#include<stdio.h>
#define max 1000
int c[max],temp[max];
//	c是保存多项式的数组,c[i]代表X^i的系数
//  temp是临时多项式,保存相乘的临时中间情况 
int main()
{
/*程序将多项式两两相乘,最开始第一个和第二个多项式相乘, 
然后将结果看成新的第一个多项式,与接下来的多项式相乘,
依次类推,c始终存放当前运算后的结果,然后作为被乘多项式。 
 */
	int num;//目标重量  比如上面例子中,num=10(num<max) 
	int i,j,k;
	while(scanf("%d",&num)!=EOF)
	{
		for(i=0;i<=num;i++)//初始化第一个多项式,
		//也就是用1g砝码组成的多项式,如果题目给的不是1g
		//就不能写成i++,应该加上砝码的质量 
		{
			c[i]=1;
			temp[i]=0;//但是不管最开始的砝码质量是多少
			//temp必须全部置0 
		}
		for(i=2;i<=num;i++)//后面的多项式从第2项开始乘
		//如果不是规律增长,i++要修改为加上砝码的质量 
		{
			for(j=0;j<=num;j++) //前一项乘后一项 
				for(k=0;k+j<=num;k+=i) //因为j=0的时候k+0会把所有值都加到,所以,temp[i]不会等于0 
					temp[j+k]+=c[j];//前一项的系数是c[j],后一项是系数都是1 
			for(j=0;j<=num;j++)//将临时结果覆盖当前结果,把临时结果置0 
			{
				c[j]=temp[j];
				temp[j]=0;
			}
		} 
		printf("%d\n",c[num]);
	}
	return 0;
}

套用母函数:
HDU 2152:https://blog.csdn.net/qq_37230495/article/details/88234611
HDU 2082:https://blog.csdn.net/qq_37230495/article/details/88092043
HDU 1398:https://blog.csdn.net/qq_37230495/article/details/88237760
HDU 1284:https://blog.csdn.net/qq_37230495/article/details/88231795
HDU 1085:https://blog.csdn.net/qq_37230495/article/details/88233606

猜你喜欢

转载自blog.csdn.net/qq_37230495/article/details/88090685