Description
一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数。
Input
第一行是一个正整数n,表示树有n个结点。第二行有n个数,第i个数表示di,即树的第i个结点的度数。其中1<=n<=150,输入数据保证满足条件的树不超过10^17个。
Output
输出满足条件的树有多少棵。
Sample Input
4
2 1 2 1
Sample Output
2
题解:首先需要知道有个东西叫prufer数列。然后可以发现一个节点在prufer数列中出现的次数是这个节点的度数减一。这样我们就知道这个数列中有哪些数了。因为一个prufer数列唯一对应一颗树。然后问题就变成了求有多少种prufer数列。又因为我们知道了元素种类与出现次数。于是问题就变成了求一个有重复元素的全排列。
因为n最大有150.所以分解一下质因数就好了。
注意一开始要先判断是否有解。即把所有点的度数减一然后加起来,如果不等于n-2就无解。
#include<cstdio> using namespace std; int n,tot,p[2][151],x; long long ans(1); void cal(int x,int k) { for (int i=2;;i++) { if (x%i==0) while (x%i==0) {p[k][i]++;x/=i;} if (x==1) break; } } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&x); if (x>2) { for (int j=1;j<=x-1;j++) cal(j,1); } if (x>1) tot+=x-1; } if (n==1) {printf("%d",!x);return 0;} if(tot!=n-2) {printf("0");return 0;} for (int i=2;i<=tot;i++) cal(i,0); for (int i=1;i<=150;i++) if (p[0][i]-p[1][i]>0) for (int j=1;j<=p[0][i]-p[1][i];j++) ans*=(long long)i; printf("%lld",ans); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-05 21:39:12