【BZOJ】【1211】【HNOI2004】树的计数
2015-05-15 17:44
288 查看
Prufer序列+组合数学
嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明的烦恼)那么我们令每个点的度数v[i]-1,得到每个节点在prufer序中的出现次数!
现在就是求这个prufer序有多少种了……有两种做法:
1.多重集排列数:n个元素,每种元素有a[i]个,求全排列的方案数,自己随便yy一下就可以得到$$ans=\frac{n!}{\prod (a[i]!)}$$
意义就是:n个人全排列的数目是N!,然而对于第一种人,这a[1]个人站的顺序不同也只算一种,所以要除以(a[1]!),以此类推,得到上述表达式。
/************************************************************** Problem: 1211 User: ProgrammingApe Language: C++ Result: Accepted Time:0 ms Memory:1288 kb ****************************************************************/ //BZOJ 1211 #include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define pb push_back using namespace std; typedef long long LL; inline LL getint(){ LL r=1,v=0; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; return r*v; } const int N=401; /*******************template********************/ LL n,m,a ,ans,fac ,prime ,tot; LL b ; bool vis ; void ready(int n){ F(i,2,n){ if (!vis[i]) prime[++tot]=i; F(j,1,tot){ if (i*prime[j]>n) break; vis[i*prime[j]]=1; if (i%prime[j]==0) break; } } } void add(int k,int v){ // printf("add %d %d\n",k,v); F(j,1,tot){ int x=k; while(x){ b[j]+=x/prime[j]*v; x/=prime[j]; } } } inline void C(int a,int b){ add(a,1); add(b,-1); add(a-b,-1);} int main(){ #ifndef ONLINE_JUDGE freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); #endif ready(300); n=getint(); if (n==1){ a[1]=getint(); if (a[1]!=0) {puts("0"); return 0;} else {puts("1"); return 0;} } F(i,1,n){ a[i]=getint()-1; if (a[i]<0 || a[i]>n-1) {puts("0"); return 0;} m+=a[i]; } if (m!=n-2){puts("0"); return 0;} F(i,1,n) if (a[i]){ C(m,a[i]); m-=a[i]; // F(j,1,4) cout <<prime[j]<<' '<<b[j]<<endl; } // add(m,1); // F(i,1,n) add(a[i],-1); ans=1; // F(j,1,4) cout <<prime[j]<<' '<<b[j]<<endl; F(i,1,tot) F(j,1,b[i]) ans*=prime[i]; printf("%lld\n",ans); return 0; }
View Code(组合数,处理阶乘时直接处理n,分解质因数)
嗯在看代码之前还有几句要说:这题有$n\leq 150$,所以直接预处理阶乘是不太现实的……所以在这里我用了分解质因数进行快速乘除(这样做高精乘除快->变成质因子次数的加减,普通高精加减快)
然后也学到了一种快速对阶乘进行因式分解的姿势>_<happy~
1211: [HNOI2004]树的计数
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1458 Solved: 469
[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
42 1 2 1
Sample Output
2HINT
Source
组合数学[Submit][Status][Discuss]
相关文章推荐
- bzoj1211: [HNOI2004]树的计数(purfer编码)
- bzoj1211 [HNOI2004]树的计数 prufer序列
- [BZOJ1211][HNOI2004][prufer序列][排列]树的计数
- bzoj1211 [HNOI2004]树的计数 prufer序列+组合数
- BZOJ 1211 HNOI2004 树的计数 Prufer序列
- 【BZOJ】1211 [HNOI2004]树的计数 prufer编码+组合数学+高精度
- 【bzoj1211】 HNOI2004—树的计数
- 4000 [BZOJ 1211][HNOI2004]树的计数(prufer编码+组合数学)
- 【BZOJ1005/1211】[HNOI2008]明明的烦恼/[HNOI2004]树的计数 Prufer序列+高精度
- 【BZOJ 1211】 1211: [HNOI2004]树的计数 (prufer序列、计数)
- 洛谷 P2290 [HNOI2004]树的计数(bzoj[1211])
- bzoj 1211: [HNOI2004]树的计数 -- purfer序列
- BZOJ 1211 HNOI2004 树的计数 Prufer序列
- 【BZOJ 1211】 [HNOI2004]树的计数
- 【BZOJ1211】【HNOI2004】树的计数
- bzoj1211: [HNOI2004]树的计数
- BZOJ1211 - [HNOI2004]树的计数
- [BZOJ1211][HNOI2004]树的计数(Prufer序列)
- BZOJ 1211: [HNOI2004]树的计数
- 【组合数学】【prufer数列】【HNOI 2004】【bzoj 1211】树的计数