【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;
}