BZOJ P1211:[HNOI2004]树的计数
来源:互联网 发布:淘宝直通车删除计划 编辑:程序博客网 时间:2024/05/16 07:29
第一次学prufer数列相关,一开始觉得可能可以树形DP但发现复杂度大的我无法想象
然后发现是prufer数列
具体相关的知识可以自行去百度,下面是我搜到的一些资料
将树转化成Prufer数列的方法
一种生成Prufer序列的方法是迭代删点,直到原图仅剩两个点。对于一棵顶点已经经过编号的树T,顶点的编号为{1,2,...,n},在第i步时,移去所有叶子节点(度为1的顶点)中标号最小的顶点和相连的边,并把与它相邻的点的编号加入Prufer序列中,重复以上步骤直到原图仅剩2个顶点。
例子
Prufer数列
以右边的树为例子,首先在所有叶子节点中编号最小的点是2,和它相邻的点的编号是3,将3加入序列并删除编号为2的点。接下来删除的点是4,5被加入序列,然后删除5,1被加入序列,1被删除,3被加入序列,此时原图仅剩两个点(即3和6),Prufer序列构建完成,为{3,5,1,3}将Prufer数列转化成树的方法
设{a1,a2,..an-2}为一棵有n个节点的树的Prufer序列,另建一个集合G含有元素{1..n},找出集合中最小的未在Prufer序列中出现过的数,将该点与Prufer序列中首项连一条边,并将该点和Prufer序列首项删除,重复操作n-2次,将集合中剩余的两个点之间连边即可。
例子
仍为上面的树,Prufer序列为{3,5,1,3},开始时G={1,2,3,4,5,6},未出现的编号最小的点是2,将2和3连边,并删去Prufer序列首项和G中的2。接下来连的边为{4,5},{1,5},{1,3},此时集合G中仅剩3和6,在3和6之间连边,原树恢复
然后我们发现一个prufer数列非常nice的性质:
就是一个节点在prufer数列中出现的次数是这个节点度数减一
很好证明,如果这个点是叶子节点那么不会出现的啊,即为0
如果不是叶子节点,那么每一次他的叶子节点被删时,他的度数减一,减到为一时,即为叶子节点了,所以出现次数为度数减一
然后排列组合一算就可以了
发现题目中n很小,直接质因数分解一下就可以了,不需要高精度
然后的话,通过prufer的定义,我们会发现,到最后prufer数列的中的数一共有n-2个
至于prufer数列的个数一共有n-2的证明我补上一下,其实非常显然,我每加一个点必须先删掉一个点
那么非常显然的是我一共要删n-2个点,那么prufer序列中的数一共有n-2个
那么所有的数的度数减一的和不为n-2就没有方案了
下面是代码
#include<iostream>#include<algorithm>using namespace std;int n,tot,p[2][151],x;long long ans(1);void cal(int x,int k){ for(int i=2;;i++){ while(x%i==0){p[k][i]++,x/=i;} if(x==1){ break;} }}//直接把数字质因数分解记录进数组里面long long qpow(int x,int y){if(y==1){return x;}else{long long fanhui=qpow(x,y/2);if(y%2==1){fanhui*=x;}return fanhui;}}//快速幂 int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>x; if(x>2){ for(int j=1;j<=x-1;j++){ cal(j,1);} }//当x>2时,拆开记录一个p数组中 if(x>1){ tot+=x-1;}//记所有点的度数减一然后加起来 } if(n==1){cout<<!x<<endl;return 0;}//特判只有一个节点的情况 if(tot!=n-2){cout<<0<<endl;return 0;}//所有点的度数减一之和不为n-2的话就无解 for(int i=2;i<=tot;i++){ cal(i,0);}//将tot!拆开存到另一个p数组里 for(int i=1;i<=150;i++){ if(p[0][i]-p[1][i]>0){//若某一因子多了,那么算进答案中 ans*=(long long)qpow(i,p[0][i]-p[1][i]);}}//算答案 cout<<ans<<endl; return 0;}/*in:42 1 2 1out:2*/
0 0
- BZOJ P1211:[HNOI2004]树的计数
- [Prufer] BZOJ 1211 [HNOI2004]树的计数
- BZOJ 1211 [HNOI2004] 树的计数
- [bzoj]1211: [HNOI2004]树的计数
- BZOJ 1211: [HNOI2004]树的计数
- bzoj 1211[HNOI2004]树的计数
- bzoj 1211: [HNOI2004]树的计数
- bzoj 1211: [HNOI2004]树的计数
- BZOJ 1211 HNOI2004 树的计数
- BZOJ 1211 HNOI2004 树的计数 Prufer序列
- BZOJ 1211: [HNOI2004]树的计数 prufer编码
- 洛谷 P2290 [HNOI2004]树的计数(bzoj[1211])
- bzoj1211: [HNOI2004]树的计数
- bzoj1211: [HNOI2004]树的计数
- 【bzoj1211】 [HNOI2004]树的计数
- BZOJ 题目1211: [HNOI2004]树的计数(组合数学,prufer)
- [BZOJ 1211][HNOI2004]树的计数(prufer编码+组合数学)
- bzoj 1211: [HNOI2004]树的计数 (prufer序列+组合数学)
- 效果演示
- oracle 常用日期函数 (sysdata、日期格式)
- 自己的sublime配置
- 剑指Offer(15)______反转链表
- java自定义注解实例
- BZOJ P1211:[HNOI2004]树的计数
- SQL SERVER重置自动编号列(标识列)
- java中使用Socket实现两个界面同步
- BZOJ4762 最小集合
- IDA*——BZOJ1085/Luogu2324 [SCOI2005] 骑士精神
- centos 安装jdk并设置环境变量
- 第三章
- 六角填数
- 剑指Offer(16)______合并两个排序的链表