bzoj 1211: [HNOI2004]树的计数 prufer编码
2016-11-17 20:49
375 查看
题意
一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数。分析
可以知道一组prufer编码唯一对应着一棵树,一棵树也唯一对应着一组prufer编码。对于一棵给定所有节点度数的树,显然每个点会在prufer编码中出现d-1次,那么我们排列组合一下就得到了
ans=(n−2)!d[1]!d[2]!...d[k]!
乘的时候只要分解一下质因数即可。
注意特判n=1时的情况。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define N 160 using namespace std; int t ,not_prime ,prime ,tot,n,d ; void get_prime(int n) { for (int i=2;i<=n;i++) { if (!not_prime[i]) prime[++tot]=i; for (int j=1;j<=tot&&prime[j]*i<=n;j++) { not_prime[prime[j]*i]=1; if (i%prime[j]==0) break; } } } void solve(int x,int y) { for (int k=2;k<=x;k++) { int w=k; for (int j=1;j<=tot;j++) if (w%prime[j]==0) { while (w%prime[j]==0) { t[j]+=y; w/=prime[j]; } } } } int main() { scanf("%d",&n); if (n==1) { int x; scanf("%d",&x); if (!x) printf("1"); else printf("0"); return 0; } get_prime(n); int s=0; for (int i=1;i<=n;i++) { scanf("%d",&d[i]); if (!d[i]) { printf("0"); return 0; } d[i]--; s+=d[i]; } if (s!=n-2) { printf("0"); return 0; } solve(n-2,1); for (int i=1;i<=n;i++) if (d[i]>1) solve(d[i],-1); ll ans=1; for (int i=1;i<=tot;i++) for (int j=1;j<=t[i];j++) ans=(ll)ans*prime[i]; printf("%lld",ans); return 0; }
相关文章推荐
- bzoj1211: [HNOI2004]树的计数 prufer编码
- BZOJ 1211: [HNOI2004]树的计数 prufer编码
- 【bzoj1211】 [HNOI2004]树的计数
- bzoj 1211[HNOI2004]树的计数
- 【BZOJ1211】树的计数(HNOI2004)-Prufer序列+组合计数
- [BZOJ1211][HNOI2004]树的计数(Prufer序列)
- bzoj1211 [HNOI2004]树的计数 prufer序列
- 【组合数学】【prufer数列】【HNOI 2004】【bzoj 1211】树的计数
- BZOJ1211: [HNOI2004]树的计数
- 【bzoj1211】 HNOI2004—树的计数
- bzoj 1211: [HNOI2004]树的计数
- 【BZOJ1211】【HNOI2004】树的计数 prufer序列
- 【BZOJ】1211 [HNOI2004]树的计数 prufer编码+组合数学+高精度
- bzoj1211: [HNOI2004]树的计数(purfer编码)
- 4000 [BZOJ 1211][HNOI2004]树的计数(prufer编码+组合数学)
- bzoj 1211: [HNOI2004]树的计数
- 【prufer编码】BZOJ1211 [HNOI2004]树的计数
- 【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)
- bzoj 1211: [HNOI2004]树的计数 -- purfer序列
- bzoj1211: [HNOI2004]树的计数