[HNOI2004]树的计数
注意点:
- 度数为
一定无解0 - 度数减一的和不等于点数
一定无解− 2 - 数据保证满足条件的树不超过
个,但要用高精1 0 1 7 (然而并不需要,呵呵)
其他的就跟模板题一样了~
Problem
题目描述
一个有
给定
输入格式
第一行是一个正整数
第二行有
其中
输出格式
输出满足条件的树有多少棵。
输入
42 1 2 1
输出
2
Code
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;struct bigint{ mutable int a[1005]; inline int& operator[](size_t pos)const{return a[pos];} inline bigint(){memset(a,0,sizeof(a));a[0]=1;} inline bigint& operator*=(int b) { int i; for(i=1;i<=a[0];++i)a[i]*=b; for(i=1;i<=a[0]||a[i];++i) { if(a[i]>=10000) { a[i+1]+=a[i]/10000; a[i]%=10000; } } a[0]=i-1; return *this; }}ans;inline ostream& operator<<(ostream& os,const bigint& a){ printf("%d",a[a[0]]); for(int i=a[0]-1;i>=1;--i)printf("%04d",a[i]); return os;}int num[1005],d[1005],p[1005],cnt;bool vis[1005];inline void Solve(int x,int del){ int i,j,s; for(i=1;i<=cnt&&p[i]<=x;++i) { s=p[i]; while(s<=x) { num[i]+=(x/s)*del; s*=p[i]; } } return;}inline void Init(){ int i,j; for(i=2;i<=1000;++i) { if(!vis[i])p[++cnt]=i; for(j=1;j<=cnt&&i*p[j]<=1000;++j) { vis[i*p[j]]=1; if(i%p[j]==0)break; } } return;}int main(void){ Init(); int i,j,x,n,m=0; long long sum=0; scanf("%d",&n); if(n==1) { scanf("%d",&x); if(!x)printf("1\n"); else printf("0\n"); return 0; } for(i=1;i<=n;++i) { scanf("%d",&d[i]); if(d[i]==0){printf("0\n");return 0;} --d[i];sum+=d[i]; } if(sum!=n-2){printf("0\n");return 0;} Solve(n-2,1); Solve(n-sum-2,-1); for(i=1;i<=n;++i) { if(d[i]>0)Solve(d[i],-1); } ans[1]=1; for(i=1;i<=cnt;++i) { for(j=1;j<=num[i];++j)ans*=p[i]; } for(i=1;i<=n-sum-2;++i)ans*=m; cout<<ans<<endl; return 0;}