【prufer编码】BZOJ1211 [HNOI2004]树的计数
2015-06-22 19:27
316 查看
Description
给定一棵树每个节点度的限制为di,求有多少符合限制不同的树。Solution
发现prufer码和度数必然的联系prufer码一个点出现次数为它的度数-1
我们依然可以把树转成序列进行处理
只是每个元素出现次数受到了限制
于是就是有重复元素的排列问题了
公式很好推
Code
特殊情况判一判#include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; const int maxn=155; int dy[maxn],pri[maxn]; int tot[maxn],cnt; int d[maxn],n,sum; int getpri(){ for(int i=2;i<=n;i++){ if(!dy[i]) pri[++cnt]=i,dy[i]=cnt; for(int j=1;j<=cnt&&i*pri[j]<=n;j++){ dy[pri[j]*i]=j; if(i%pri[j]==0) break; } } } int add(int x,int k){ while(x!=1){ tot[dy[x]]+=k; x/=pri[dy[x]]; } } ll pow(ll x,ll k){ ll ret=1; for(int i=k;i;i>>=1,x=x*x) if(i&1) ret=ret*x; return ret; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&d[i]),sum+=d[i]; if(sum!=2*n-2){ printf("0\n"); return 0; } if(n==1){ printf("1\n"); return 0; } getpri(); for(int i=1;i<=n-2;i++) add(i,1); for(int i=1;i<=n;i++) if(!d[i]){ printf("0\n"); return 0; } else for(int j=1;j<d[i];j++) add(j,-1); ll ans=1; for(int i=1;i<=cnt;i++) ans=ans*pow(1ll*pri[i],tot[i]); printf("%lld\n",ans); return 0; }
相关文章推荐
- socket.io + nodes 实现webSocket消息提醒
- 【prufer编码】BZOJ1430 小猴打架
- ./cts-tradefed run error[REASON:java config is not right]
- class 添加样式,删除,开关 【选择】addClass,removeClass,toggleClass
- Jquery1.6版本后attr的变化,灰常委屈
- ReactJS -- 初学入门
- jquery easyui常见问题:
- html控件使用
- 图解JavaScript 继承
- JavaScript学习笔记(数组篇)
- jsp的自定义标签
- js--小结④
- 一个线程往缓冲区buffer写数据,另外三个读数据,读和写要分开
- jquery多选下拉框左右复制
- angularjs实战项目01-构建开发环境
- CSS width:100%和width:auto的区别
- Grunt + Bower—前端构建利器(转)
- Unable to compile class for JSP
- angularjs 中行的选定及行样式的设定
- HTML5 manifest离线缓存