【BZOJ1211】【HNOI2004】树的计数 prufer序列

题目描述

  给你\(n\)\(n\)个点的度数,问你有多少个满足度数要求的生成树。

  无解输出\(0\)。保证答案不超过\({10}^{17}\)

  \(n\leq 150\)

题解

  考虑prufer序列。

  答案为

\[\frac{(n-2)!}{\prod(d_i-1)!} \]

  直接乘会爆long long,要转成\(n-1\)个组合数的乘积。当然你也可以分解质因数。

  如果\(n\neq 1\)\(d_i=1\),输出\(0\)

  如果\(\sum d_i\neq 2n-2\),输出\(0\)

  时间复杂度:\(O(n^2)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
ll c[200][200];
int d[200];
int main()
{
	int n;
	scanf("%d",&n);
	int i,j;
	int sum=0;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&d[i]);
		if(n!=1&&d[i]<=0)
		{
			printf("0\n");
			return 0;
		}
		sum+=d[i];
	}
	if(sum!=2*n-2)
	{
		printf("0\n");
		return 0;
	}
	for(i=0;i<=n;i++)
	{
		c[i][0]=1;
		for(j=1;j<=i;j++)
			c[i][j]=c[i-1][j]+c[i-1][j-1];
	}
	ll ans=1;
	ll s=0;
	for(i=1;i<=n;i++)
	{
		ans*=c[s+d[i]-1][d[i]-1];
		s+=d[i]-1;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-03-06 07:25  ywwyww  阅读(169)  评论(0编辑  收藏  举报