1211: [HNOI2004]树的计数
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1565 Solved: 512
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
题解:
是明明的烦恼的弱化版。。做法大体相同,不用高精度真是开心。
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 210
#define LL long long
int n,s,d[N],su[N],ys[N];
LL jc[30],ans;
int in(){
int x=0; char ch=getchar();
while (ch<‘0‘ || ch>‘9‘) ch=getchar();
while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
return x;
}
void init(){
jc[0]=jc[1]=1;
for (int i=2; i<=25; i++) jc[i]=jc[i-1]*(LL)i;
for (int i=2; i<=N; i++){
bool f=true;
for (int j=2; j<=sqrt(i); j++)
if (!(i%j)){
f=false; break;
}
if (f) su[++su[0]]=i;
}
}
void fenjie(int x,int y){
for (int i=1; i<=su[0]; i++){
if (x<=1) return;
while (!(x%su[i]))
ys[i]+=y,x/=su[i];
}
}
int main(){
scanf("%d",&n);
if (n==1){
int x=in();
if (!x) ans=1;
else ans=0;
printf("%d\n",ans);
return 0;
}
for (int i=1; i<=n; i++){
d[i]=in();
if (!d[i]){
printf("0\n");
return 0;
}
d[i]--,s+=d[i];
}
if (s!=n-2){
printf("0\n");
return 0;
}
init(); ans=1;
if (n-2<=25) fenjie(jc[n-2],1);
for (int i=1; i<=n; i++)
fenjie(jc[d[i]],-1);
for (int i=1; i<=su[0]; i++)
while (ys[i]--) ans*=su[i];
printf("%d\n",ans);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-11 14:59:15