生成函数

定义:

对于序列a0,a1,a2,...,an,构造一个函数:

G(x) = a0+a1*x+a2*x^2+...+an*x^n

称G(x)为序列a0,a1,a2,...,an的生成函数(或者母函数)。

用途:

1.“把组合问题的加法法则和幂级数的乘幂对应起来”

2.“母函数的思想很简单 — 就是把离散数列和幂级数一 一对应起来,把离散数列间的相互结合关系对应成为幂级数间的运算关系,最后由幂级数形式来确定离散数列的构造. “

相关blog:

普通母函数:http://www.wutianqi.com/?p=596

指数型母函数:http://www.wutianqi.com/?p=2644

实现:

普通母函数(适用于组合问题)
问题:设有n种砝码,每种砝码的重量由数组a[n]表示,每种砝码的个数用数组b[n]表示,求称重量为m的物体有多少种方案?
由题可以列出母函数表达式:

题目的解为G(x)的幂次为m的项系数。
int GeneratingFunction(int a[], int b[], int n, int m)
{
	int N = 0;
	for(int i=0; i<n; ++i)
		N += a[i]*b[i];
	int *value = new int[N];
	int *temp = new int[N];
	if(!value || !temp)
	{
		cout << "Out of memory!" << endl;
		return -1;
	}
	memset(temp, 0, N*sizeof(int));
	memset(value, 0, N*sizeof(int));
	fill(value, value+b[0]+1, 1);

	int max_power_cnt = b[0]*a[0];
	//逐项展开
	for(int i=1; i<n; ++i)
	{
		for(int j=0; j<=max_power_cnt; ++j)
			for(int k=0; k<=b[i]*a[i]; k+=a[i])
				temp[k+j] += value[j];
		max_power_cnt += b[i]*a[i];
		memcpy(value, temp, max_power_cnt*sizeof(int));
		memset(temp, 0, N*sizeof(int));
	}
	int r = value[m];
	delete [] value;
	delete [] temp;
	return r;
}

例:(1)设有重量为1,2,3,4的砝码各一个,某物体重量为5,求称该物体有几种组合方式?

int a[4] = {1,2,3,4};
int b[10] = {1,1,1,1};
cout << GeneratingFunction(a, b, 4, 5) << endl;

(2)将整数10拆分,有多少种方案?
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int b[10] = {10,10,10,10,10,10,10,10,10,10};
cout << GeneratingFunction(a, b, 10, 10) << endl;

指数型母函数(适用于排列问题)
问题:有n种不同颜色的球,每种颜色的球的个数用数组a[n]表示,问取m个球进行排列,有多少种方案?

由题可以列出母函数表达式:


题目的解为G(x)的幂次为m的项系数。

#define MAX 50
double value[MAX],temp[MAX]; 
int fac(int i)
{
	if(i==0)
		return 1;
	return i*fac(i-1);
}
int GeneratingFunctionE(int a[], int n, int m)
{
	int N = 0;
	for(int i=0; i<n; ++i)
		N += a[i];
	if(N>MAX)
	{
		cout << "Out of memory!" << endl;
		return -1;
	}

	memset(temp, 0, MAX*sizeof(double));
	memset(value, 0, MAX*sizeof(double));
	for(int i=0; i<=a[0]; ++i)
		value[i] = 1/(double)fac(i);

	int max_power_cnt = a[0];
	//逐项展开
	for(int i=1; i<n; ++i)
	{
		for(int j=0; j<=max_power_cnt; ++j)
			for(int k=0; k<=a[i]; k++)
				temp[k+j] += value[j]/(double)fac(k);
		max_power_cnt += a[i];
		memcpy(value, temp, (max_power_cnt+1)*sizeof(double));
		memset(temp, 0, MAX*sizeof(double));
	}
	return (int)(value[m]*fac(m));
}

例:有红球三个,白球两个、黄球三个,去除7个球的排列数为多少?

int a[3] = {3,2,3};
cout << GeneratingFunctionE(a, 3, 7) << endl;


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值