一棵树的Prufer数列

  每次在剩下的树中找到标号最小的叶子节点(对于无根树而言即是度数为1的节点),删去。

  同时将其父节点(即与其相连的唯一点)加入Prufer数列当中。

一个Prufer数列所对应的树

  G集合开始为空集

  设当前处理到Prufer数列的第i项,找到G集合中未出现且在Prufer[i..n-2]未出现过的标号最小的节点,设其为u。

  将u加入集合G中,并将u与Prufer[i]连一条边。

  最后将在G集合中仍未出现的两个点之间连一条边(其中必定有一个是n)。

来思考一下为何可以还原成最初的树

  首先我们可以把加入G集合这个操作当成是删去叶子节点的操作。

  在G集合中未出现代表这个数还在树上未被删去。

  再Prufer[i..n-2]中未出现代表这个节点当前的度数为1,即是叶子节点。

  所以找出的u其实就等同于标号最小的叶子节点。

显然,树和Prufer数列一一对应。

即对于一棵树有且仅有一个Prufer数列

对于一个Prufer数列能且仅能还原出唯一的一棵树。

一些性质

  每一个Prufer数列有n-2项(n为节点的个数)

  对于一个度数为x的节点,它在Prufer数列中出现x-1次

  对于满足上述两个条件的Prufer数列(当然每个数不能超过n)必能构成一棵合法的树

  有了这个想法便可以开始做这道题。

  即求可能的Prufer数列的个数。

  转化为一个排列组合问题

  对于cnt个有度数限制的节点,其a[i]-1的加和我们设为sum,则要在Prufer数列的n-2个空位中选sum的位置放这cnt个点

  对于剩下的n-sum-2个空位可以放任意的没有度数限制的点。

  (n-2)!*(n-cnt)n-sum-2/(∏(a[i]-1)!*(n-sum-2)!)

  求解上述式子可以用分解质因子的方法,对于阶乘的分解可以采用更快的方法。

  最后高精度乘法。

program bzoj1005;
const maxn=;tt=;
type arr=array[-..maxn]of longint;
var n,cnt,sum,i,j:longint;
a,p,w:array[-..maxn]of longint;
vis:array[-..maxn]of boolean;
ans:arr;
ss:string;
procedure printf;
begin
writeln();
halt;
end; procedure build;
var i,j:longint;
begin
fillchar(vis,sizeof(vis),true);
p[]:=;
for i:= to maxn do
begin
if vis[i] then
begin
inc(p[]);
p[p[]]:=i;
end;
for j:= to p[] do
begin
if i*p[j]>maxn then break;
vis[i*p[j]]:=false;
if i mod p[j]= then break;
end;
end;
end; procedure work(x,y:longint);
var i,xx,tot:longint;
begin
xx:=x;
for i:= to p[] do
begin
x:=xx;tot:=;
while x<> do
begin
inc(tot,x div p[i]);
x:=x div p[i];
end;
inc(w[i],tot*y);
end;
end; procedure work2(x,y:longint);
var i,tot:longint;
begin
for i:= to p[] do if x mod p[i]= then
begin
tot:=;
while x mod p[i]= do
begin
inc(tot);x:=x div p[i];
end;
inc(w[i],tot*y);
end;
end; function mul(a:arr;b:longint):arr;
var c:arr;
i:longint;
begin
fillchar(c,sizeof(c),);
c[]:=a[];
for i:= to c[] do
begin
inc(c[i],a[i]*b);
inc(c[i+],c[i] div tt);
c[i]:=c[i] mod tt;
end;
if c[c[]+]<> then inc(c[]);
exit(c);
end; begin
//assign(input,'bzoj1005.in');reset(input);
//assign(output,'bzoj1005.out');rewrite(output);
readln(n);
cnt:=;sum:=;
for i:= to n do
begin
readln(a[i]);
if a[i]> then inc(cnt) else
if a[i]= then printf;
if a[i]> then inc(sum,a[i]-);
end;
fillchar(w,sizeof(w),);
if sum>n- then printf;
build;
work(n-,);
work(n--sum,-);
work2(n-cnt,n-sum-);
for i:= to n do if a[i]> then work(a[i]-,-);
ans[]:=;ans[]:=;
for i:= to p[] do
for j:= to w[i] do ans:=mul(ans,p[i]);
write(ans[ans[]]);
for i:=ans[]- downto do
begin
str(ans[i],ss);
for j:=length(ss)+ to do write();
write(ans[i]);
end;
end.

[BZOJ1005]Prufer数列+排列组合的更多相关文章

  1. [bzoj 1005][HNOI 2008]明明的烦恼(prufer数列+排列组合)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1005 分析: 首先prufer数列:http://baike.baidu.com/view/1 ...

  2. 【专题】计数问题(排列组合,容斥原理,Prufer序列)

    [容斥原理] 对于统计指定排列方案数的问题,一个方案是空间中的一个元素. 定义集合x是满足排列中第x个数的限定条件的方案集合,设排列长度为S,则一共S个集合. 容斥原理的本质是考虑[集合交 或 集合交 ...

  3. [HNOI2004]树的计数 prufer数列

    题面: 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,你的程序需要输出满足d( ...

  4. hdu1521 排列组合(指数型母函数)

    题意: 有n种物品,并且知道每种物品的数量ki.要求从中选出m件物品的排数.         (全题文末) 知识点: 普通母函数 指数型母函数:(用来求解多重集的排列问题) n个元素,其中a1,a2, ...

  5. C++写一个排列组合小程序

    今天突然想到一个问题,有时候,针对同一个事件有多种反映,特别是游戏AI当中,这种情况下需要采取最适合的方案,哪种方案最适合,可以将每种方案的结果或影响都计算一遍,从而选择最合适的.最基本就是一个排列组 ...

  6. Go语言实现列出排列组合

    今天,隔壁坐的小朋友给我一串数字: 1 6 21 55 让我观察规律,然后帮他推导公式. 尼玛,当我是神呢?!! 想了半天没看出个原委, 于是看了他那边具体需要才发现他那边是对N个数字进行5个数字的组 ...

  7. BZOJ 1211[HNOI2004]树的计数 - prufer数列

    描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...

  8. 洛谷P1246编码问题-排列组合,分类讨论

    编码问题 题意就是a,b,c.....ab.....编码,给你一个字符串,输出这是第几个: 这里可以用暴力枚举,但也可以用组合数学的高超知识: 既然这样我就说一下排列组合的方法,如果要弄一个 各位数字 ...

  9. 学习sql中的排列组合,在园子里搜着看于是。。。

    学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...

随机推荐

  1. Delphi实例之一个简易的浏览器的实现

    Delphi实例之一个简易的浏览器的实现 Delphi7的WebBrowser组件提供了很多不错的网页设计的功能,下面做一个简单的浏览器.组件很简单按照下面摆放就行了. 这是运行后的效果 源代码 主页 ...

  2. vs调试代码的时候断点无法命中

    https://blog.csdn.net/xxdddail/article/details/18696399 该链接提供的解决方案主要是如下图片:禁用 图片标记的这个选项即可:

  3. 【BZOJ 1269】文本编辑器

    题目 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对"文本编辑器"做了一个抽象的定义: Move k:将 ...

  4. Android中StackOverflow的问题

    最近出现了一个让人抓狂的问题. 现在的项目中,制作了一个界面非常复杂.Fragment中嵌套下拉刷新的Listview 这样一个布局,在3.0以上的手机上都表现良好问题!但是在2.x的比较弱爆的手机上 ...

  5. js解决img标签加载失败显示默认图片

    问题: 为所有显示楼盘的页面添加一个加载失败的默认图片. 基本思路: img标签中有个onerror属性,专门用来处理加载失败的事件.所以可以用jquery添加onerror属性,在onerror中加 ...

  6. 「暑期训练」「Brute Force」 Money Transfers (CFR353D2C)

    题目 分析 这个Rnd353真是神仙题层出不穷啊,大力脑筋急转弯- - 不过问题也在我思维江化上.思考任何一种算法都得有一个“锚点”,就是说最笨的方法怎么办.为什么要这么思考,因为这样思考最符合我们的 ...

  7. Vm-Ubuntu下配置Qt开发环境

    在昨天的Ubuntu换降下,安装Qt发现编译的时候是缺少opengl的 奈何找了好多方式都无法安装opengl 今天看到另一位大神写的,才发下自己找的还是有问题 大神帖子网址:http://blog. ...

  8. ubuntu中 VI 方向键、删除键问题

    这两天重新装的ubuntu系统,发觉使用VI时,方向键按下去后变成ABCD,删除键无效.网上搜寻一番,应该是VI软件本身的问题,顾卸载重装即可,步骤如下: 1.执行命令 sudo apt-get re ...

  9. Codeforces Round #326 Div.1 C.Duff in the Army 树上倍增

    题意概述: 给出一棵N个结点的树,然后有M个居民分散在这棵树的结点上(允许某个结点没有居民).现在给出一些询问形如u,v,a,定义k=min(x,a),其中x表示的是u->v路径上的居民数量.将 ...

  10. 福大软工1816:Alpha(2/10)

    Alpha 冲刺 (2/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1.学习qqbot库: 2.实 ...