其他分享
首页 > 其他分享> > POJ3734 Blocks (指数型生成函数)

POJ3734 Blocks (指数型生成函数)

作者:互联网

这题直接贴推公式图,多重集合的 n n n排列组合数的定理证明需自行了解
在这里插入图片描述
问题一般问得很明确,每个元素可以重复出现,但是每个又有特殊的限制,然而总量是固定的 n n n,问排列数量有多少个?(也就是给出了总数每个物体的种数

那么把公式推出来之后,基本上是套快速幂模板了。
But如果不走公式这条路(因为给的限制条件太少了,用个模拟就行了),也就是基本的模拟系数的乘法和加法。

例如下面这道HDU1521(这里补充暴力模拟展开系数解法)

值得注意的是:因为已经是暴力模拟了,出来的系数是 x n x^n xn 前面的系数,所以还要乘回 n ! n! n!,才是生成函数的系数,如果又懵了可以先回去卡看上面的公式图,如果还不懂说明定理的证明没搞明白。

题意:

n n n种物品,每种有 a i a_i ai​个,抽 m m m个的排列数?

思路:

回到常见提问:总量固定是 m m m个,而每个都有 a i a_i ai​个的限制

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 50;
const int inf = 0x3f3f3f3f;

double jc[N], coef[N], tmp[N];
int v[N]; // 每件物品数 
int main()
{
	int n, m;
	jc[0] = 1;
	for (int i = 1; i <= 10; i++)
		jc[i] = jc[i - 1] * i;
	while (cin >> n >> m)
	{
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &v[i]);  // 每个物品最多能拿,也就是括号里的最高项
			v[i] = min(v[i], m);
		} 		
		memset(coef, 0, sizeof coef);
		memset(tmp, 0, sizeof tmp);
		
		for (int i = 0; i <= v[1]; i++)  // 赋coef初值是第一个物品 
		 	coef[i] = 1.0 / jc[i];
		
		for (int i = 2; i <= n; i++) // 后面 n - 1个括号 
		{
			for (int j = 0; j <= m; j++)  // m是前面被乘()的最高项
				for (int k = 0; k <= v[i] && k + j <= m; k++)
					tmp[k + j] += coef[j] * 1.0/ jc[k];
			memcpy(coef, tmp, sizeof tmp);
			memset(tmp, 0, sizeof tmp);
		}
		
		printf("%.lf\n", coef[m] * jc[m]);
	}
    return 0;
}

标签:tmp,系数,Blocks,函数,coef,int,公式,POJ3734,模拟
来源: https://blog.csdn.net/YunTunLu/article/details/108944322