[HNOI2004][bzoj1211] 树的计数(prufer序列)
1211: [HNOI2004]树的计数
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3432 Solved: 1295
[Submit][Status][Discuss]
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
2 1 2 1
Sample Output
2
题解:
果的prufer序列计数,关于prufer序列的性质(戳这里[HNOI2008] 明明的烦恼)。
知道了prufer序列的性质这题也就迎刃而解了,这不就是求不全相异全排列个数嘛,直接套式子
$\frac{\left ( n - 2 \right )!}{\prod \left ( d[i] - 1 \right )! }$
还是hin简单的趴
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 int d[205]; 9 struct node{ 10 int m[500005]; 11 friend void operator *= (node &a,int b){ 12 int x=0; 13 for(int i=1;i<=a.m[0];i++){ 14 int y=a.m[i]*b+x; 15 a.m[i]=y%10; 16 x=y/10; 17 } 18 while(x){ 19 a.m[++a.m[0]]=x%10; 20 x/=10; 21 } 22 } 23 friend void operator /= (node &a,int b){ 24 int x=0; 25 for(int i=a.m[0];i>=1;i--){ 26 x+=a.m[i]; 27 a.m[i]=x/b; 28 x%=b; 29 x*=10; 30 } 31 while(a.m[a.m[0]]==0&&a.m[0]>1) a.m[0]--; 32 } 33 friend void print(node a){ 34 for(int i=a.m[0];i>=1;i--) printf("%d",a.m[i]); 35 puts(""); 36 } 37 }ans; 38 int main(){ 39 int n,m; 40 scanf("%d",&n); 41 int sum=0; 42 ans.m[0]=ans.m[1]=1; 43 for(int i=1;i<=n;i++){ 44 scanf("%d",&d[i]); 45 if(!d[i]&&n!=1){puts("0");return 0;} 46 d[i]--; 47 sum+=d[i]; 48 } 49 if(sum!=n-2){puts("0");return 0;} 50 for(int i=1;i<=n-2;i++) ans*=i; 51 //print(ans); 52 for(int i=1;i<=n;i++){ 53 if(d[i]>0){ 54 for(int j=1;j<=d[i];j++) ans/=j; 55 } 56 } 57 print(ans); 58 }