杭电ACM——1028,Ignatius and the Princess III(母函数)

简单说明一下母函数:
G(x)=(1+a1x)(1+a2x2)…(1+anxn)
称G(x)为a1,a2,…,an,的母函数。
当a1=a2=…=an=1时,
G(x)=(1+x)(1+x2)…(1+xn)。
现在假设有这么一个问题:有四种硬币1,2,3,4各一枚,问这些硬币可以组成多少种面额?方案有多少种?
现在令
G(x)=(1+x)(1+x2)(1+x3)(1+x4)=(1+x+x2+x3)(1+x3+x4+x7)
=1+x3+x4+x7+x+x4+x5+x8+x2+x5+x6+x9+x3+x6+x7+x10
=1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10
于是,这个问题的答案就分别为10,15,怎么知道的呢?首先对于第一个答案,我们可以看x的幂次的个数(不包括1),第二个答案,我们就看x的每一项的系数(不包括1)。因此我们可以知道,母函数中,x的幂次表示价格,如x2就表示价格2,而x的系数就表示组成这种价格的方案数,如2x3就表示价格3的组成方案有2种。
那代码怎么实现呢?
本质上就是模拟前i-1个多项式与第i个多项式的相乘
杭电1028题的AC代码即为母函数的模板,如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
ll c1[121],c2[121]; //c1用于模拟操作,c2记录下结果,c1[i]的下标i表示x的幂次,c1[i]表示系数,c2同理
int main()
{
	int i,j,k; 
	int n;
	while(cin>>n) //输入的n表示最高次幂
	{
		for(i=0;i<=n;i++)  //一开始c1,c2分别初始为1,0,注意i要从0开始,c1一开始初始为1是因为c1一开始表示第一个多项式(1+x+x^2^+...x^n^),每项系数都为1
		{
			c1[i]=1;
			c2[i]=0;
		}
		for(i=2;i<=n;i++)    // i 表示多项式的编号,亦表示种类,因不同的题而不同,这里是指数字
		{
			for(j=0;j<=n;j++)  //这两步要理解好
				for(k=0;k+j<=n;k+=i)  
					c2[j+k]=c2[j+k]+c1[j];
			for(j=0;j<=n;j++)  //c2的值返回给c1,c2重新初始为0
			{
				c1[j]=c2[j];
				c2[j]=0;
			}
		}
		cout<<c1[n]<<endl;
	}
	return 0;
}

母函数的优点有:
1.题解相对固定,改一改模板一般就可以AC;
2.对于计数问题,母函数不会重复计算(如本题)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值