[HNOI2008] 明明的烦恼
2017-07-24 11:59
169 查看
[BZOJ1005][HNOI2008] 明明的烦恼
给出一棵树中所有节点的度数( −1 代表无限制),求可能的树的种类数。0<N≤1000
嘛,这是我少有的单独为一道题写的博客,这水题卡了我一晚上,不过不能否认,这道题对现在的我来说确实很有价值,本体需要先推公式,然后分解质因数搞高精。
我们考虑用 pufer 编码来表示一棵树,根据 pufer 编码的性质:
任何一棵无根树都可以表示为长度为 n−2 的串;
一个点的度数是 d ,则它会在串中出现 d−1 次。
我们知道该已知度数的节点组成的串的总长度 len=∑i=1ndi−1 ,将长度为 len 的串中的数插入到总的串中,方法有 (lenn−2) 种,而长度为 len 的串共有 (lend1−1)(len−(d1−1)d2−1)…(dn−1dn−1) 种,再算上 m 个无度数限制的节点的 mn−2−len 种,根据乘法原理:
ans===(lenn−2)(lend1−1)(len−(d1−1)d2−1)…(dn−1dn−1)mn−2−len(n−2)!(n−2−len)!len!⋅len!(d1−1)!(len−d1−1)!…(dn−1)!(dn−1)!0!⋅mn−2−len(n−2)!⋅mn−2−len(n−2−len)!∏ni=1(di−1)!
由于答案十分巨大,需要写高精,不过高精除比较恶心,所以我们考虑分解质因数。
/************************************************************** Problem: 1005 User: zhangche0526 Language: C++ Result: Accepted Time:80 ms Memory:1344 kb ****************************************************************/ #include<iostream> #include<cstdio> const int MAXN=1005; int n; int pIdx[MAXN],pri[MAXN],pcnt,dgr[MAXN]; bool notPri[MAXN]; void initPri(int r) { int i,j; for(i=2;i<=r;i++) { if(!notPri[i]) pri[++pcnt]=i; for(j=1;j<=pcnt&&pri[j]*i<=r;j++) { notPri[pri[j]*i]=true; if(i%pri[j]==0) break; } } } void addIdx(int x,int idx) { for(int i=1;i<=pcnt&&x>1;i++) while(x%pri[i]==0) x/=pri[i],pIdx[i]+=idx; } int dig[MAXN*10],dL; int main() { int i,j; initPri(1000); scanf("%d",&n); if(n==1) { scanf("%d",&dgr[1]); if(dgr[1]==0||dgr[1]==-1) printf("1\n"); else printf("0\n"); return 0; } if(n==2) { scanf("%d%d",&dgr[1],&dgr[2]); if(dgr[1]==1&&dgr[2]==1) printf("1\n"); else printf("0\n"); return 0; } int dSum=0,limNcnt=0;bool noAns=false; for(i=1;i<=n;i++) { scanf("%d",&dgr[i]); if(dgr[i]==0||dgr[i]>=n) noAns=true; if(dgr[i]==-1) continue; limNcnt++; dSum+=dgr[i]-1; for(j=1;j<=dgr[i]-1;j++) addIdx(j,-1); } for(i=1;i<=n-2;i++) addIdx(i,1); if(noAns){printf("0\n");return 0;} for(i=1;i<=n-2-dSum;i++) addIdx(i,-1); addIdx(n-limNcnt,n-2-dSum); dL=dig[1]=1; for(i=1;i<=pcnt;i++) { while(pIdx[i]) { pIdx[i]--; for(j=1;j<=dL;j++) dig[j]*=pri[i]; for(j=1;j<dL;j++) dig[j+1]+=dig[j]/10,dig[j]%=10; while(dig[dL]>=10) { dig[dL+1]+=dig[dL]/10,dig[dL]%=10; dL++; } } } for(i=dL;i;i--) printf("%d",dig[i]); printf("\n"); return 0; }
相关文章推荐
- 【Purfer】【bzoj 1005】: [HNOI2008]明明的烦恼
- 【BZOJ 1005】[HNOI2008]明明的烦恼 【Prufer序列】
- BZOJ 1005([HNOI2008]明明的烦恼-Prufer数列-树与数组的一一对应)
- 【BZOJ 1005】 1005: [HNOI2008]明明的烦恼 (prufer数列+高精度)
- bzoj1005 [HNOI2008]明明的烦恼
- BZOJ 1005 [HNOI2008]明明的烦恼
- [BZOJ1005][HNOI2008]明明的烦恼&&[BZOJ1211][HNOI2004]树的计数【prufer序列】
- 【bzoj1005】[HNOI2008]明明的烦恼
- [BZOJ1005](HNOI 2008)明明的烦恼
- BZOJ P1005:[HNOI2008]明明的烦恼
- bzoj 1005: [HNOI2008]明明的烦恼 prufer编码+高精度
- 【bzoj1005】[HNOI2008]明明的烦恼
- BZOJ 1005: [HNOI2008]明明的烦恼( 组合数学 + 高精度 )
- BZOJ 1005: [HNOI2008]明明的烦恼 Purfer数列
- HNOI2008明明的烦恼
- Bzoj1005 [HNOI2008]明明的烦恼
- [HNOI2008]明明的烦恼
- BZOJ_1005_ [HNOI2008]_明明的烦恼_(组合数学+purfer_sequence+高精度+分解因数+快速幂)
- 【bzoj_1005】[HNOI2008]明明的烦恼
- bzoj 1005: [HNOI2008]明明的烦恼 组合数学 + purfer序列