Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7155   Accepted: 4094

Description

We can number binary trees using the following scheme: 
The empty tree is numbered 0. 
The single-node tree is numbered 1. 
All binary trees having m nodes have numbers less than all those having m+1 nodes. 
Any binary tree having m nodes with left and right subtrees L and R is numbered n such that all trees having m nodes numbered > n have either Left subtrees numbered higher than L, or A left subtree = L and a right subtree numbered higher than R.

The first 10 binary trees and tree number 20 in this sequence are shown below: 

Your job for this problem is to output a binary tree when given its order number. 

Input

Input consists of multiple problem instances. Each instance consists of a single integer n, where 1 <= n <= 500,000,000. A value of n = 0 terminates input. (Note that this means you will never have to output the empty tree.)

Output

For each problem instance, you should output one line containing the tree corresponding to the order number for that instance. To print out the tree, use the following scheme:

A tree with no children should be output as X. 
A tree with left and right subtrees L and R should be output as (L’)X(R’), where L’ and R’ are the representations of L and R. 
If L is empty, just output X(R’). 
If R is empty, just output (L’)X. 

Sample Input

1 20 31117532 0

Sample Output

X ((X)X(X))X (X(X(((X(X))X(X))X(X))))X(((X((X)X((X)X)))X)X)

题目大意:根据下面的规则给一棵二叉树编号:

规则1:如果二叉树为空,则编号为0;

规则2:如果二叉树只有一个节点,则编号为1;

规则3:所有含有m个节点的二叉树的编号小于所有含有m+1个节点的二叉树的编号;

规则4:如果一棵含有m个节点的二叉树(左子树为L,右子树为R)的编号为n,要想其它含有m个节点的二叉树的编号如果大于n,则需要满足两个条件中的任意一个:1、左子树的编号大于L的编号;2、左子树的编号等于L的编号,但是右子树的编号大于R的编号。

解题方法:卡特兰数列(Catalan)+递归

Catalan数列简介:令Catalan(0)=1,Catalan(1)=1,Catalan数列满足地推公式:

Catalan(n)=Catalan(0)*Catalan(n-1)+Catalan(1)*Catalan(n-2)+...+Catalan(n-1)*Catalan(0),其中n>=2;

catalan数在这道题的理解,简单的来说就是一个节点数为n的二叉树的形态的个数,即为划分的个数

详情移步:Catalan卡塔兰数

假设f(n)表示n个节点的二叉树的所有顺序,由于左子树和右子树的顺序是相互独立的,假设0<=i<=n:表示左子树有i个节点,则右子树有n-i-1个节点(要除去根节点),则含有n个节点的二叉树,当左子树含有i个节点时,二叉树的节点顺序树为:f(i)*f(n-i-1),i从0到n-1 ,然后累加就可以求出所有f(n). 这就是一点典型的Catalan数列问题。

解题思路:

split(NodeNum,order)是用于打印问题的解的函数,其中NodeNum为当前树的结点数,order为当前树在 节点数为NodeNum的所有树中 的序号(即位次)。

(1)首先,递归框架:

 /*
递归划分结构框架
*/
void split(int NodeNum,int order)
{//NodeNum为当前子树结点数,order为当前子树在节点数为NodeNum时的序号
if(NodeNum == ) //节点数为1 直接输出X 作为递归结束条件
{cout<<"X";return;}
else
{
if(LeftNum>)//左子树不为空
{
cout<<"(";
split(,);
cout<<")";
}
cout<<"X";//打印父节点X
if(RightNum>)
{
cout<<"(";
split(,);
cout<<")";
}
}
}

NodeNum=1为递归边界条件,表示这棵子树只有一个结点,打印该结点,并返回。

(2) 计算节点数为NodeNum,序号为order的树的左右子树有多少结点,即计算LeftNum和RightNum。

由题意可知,序号为1的左子树为空,右子树结点数为order,且为右斜树(所有的节点均在右子树上并且所有节点只有右孩子);左右子树变换形态,此时左子树为空,右子树的形态数为catalan[order];当右子树遍历完所有形态后,左子树节点数加一,右子树节点数减一,生成初始状态依然为右子树为右斜树,此时左子树有节点,也为右斜树(当然此时只有一个节点,即只有根节点);左右子树变化形态,左子树形态数1,右子树形态数catalan[order-1];左子树节点数+1,右子树节点数-1,依此类推。

  当左子树有大于1个结点时,设为i个,左子树有catalan[i]种形态,左子树的每一种形态下,右子树节点数为NodeNum-i-1,形态数catalan[NodeNum-i-1]。

  整个过程就像一个时钟计时一样,左子树是时针,右子树是分针,右子树全部变化完,左子树加1,但是与时钟不同的是:时钟是60进制的,二右子树是catalan[i]进制的,i会逐渐变为0。由此可以得出二叉树中左子树的节点数LeftNum: leftNum=min(i|catalan[0]*catalan[nodeNum-1]+catalan[1]*catalan[nodeNum-2]+...+catalan[i]*catalan[NodeNum-i-1]>=order),右子树的节点数RightNum=NodeNum-LeftNum-1。

  假设  所要求的树为  含有LeftNum个结点的左子树,RightNum个结点的右子树的二叉树是NodeNum个节点的二叉树  的第NewOrder棵树,则NewOrder=order-sum,其中sum=catalan(0)*catalan(NodeNum-1)+catalan(1)*catalan(NodeNum-2)+...+catalan(LeftNum-1)*catalan(RightNum+1)。

  设左子树的应该是节点数为LeftNum的树的第LeftOrder个形态,右子树则应该是是节点数为RightNum的树的RightOrder个形态。其中LeftOrder=(NewOrder-1)/catalan(RightNum)+1,RightOrder=(NewOrder-1)%catalan(RightNum)+1。

  此处应注意模数

 #include<iostream>
using namespace std;
long catalan[] = {,,,,,,,,,,,,,
,,,,,};
void split(int NodeNum,int order)
{
if(NodeNum == ) {cout<<"X";return;}
else
{ int sum=;
int i;
for(i=;sum<order;i++)
{
sum += catalan[i]*catalan[NodeNum-i-];
}
int LeftNum = --i;//左子树的节点个数
int RightNum = NodeNum-LeftNum-;//右子树节点个数
sum = sum - catalan[LeftNum]*catalan[RightNum];
long NewOrder = order-sum;
if(LeftNum>)
{
cout<<"(";
split(LeftNum,(NewOrder-)/catalan[RightNum]+);
cout<<")";
}
cout<<"X";
if(RightNum>)
{
cout<<"(";
split(RightNum,(NewOrder-)%catalan[RightNum]+);
cout<<")";
}
}
}
int main()
{
long n;//n是序号 while(cin>>n)
{
if(n == ) return ;//0为结束
else
{
//首先得判断有几个结点
int i,sum=;
for(i=;sum<n;i++)//由于i=0不做任何操作,所以,从1开始
{
sum+=catalan[i];
}
i--;sum = sum-catalan[i];
//然后进行递归调用
split(i,n-sum);//i个结点的第n-sum种情况
}
cout<<endl; }
return ;
}

Trees Made to Order——Catalan数和递归的更多相关文章

  1. poj 1095 Trees Made to Order 卡特兰数

    这题用到了卡特兰数,详情见:http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html 解体思路详见:http://blog.csdn. ...

  2. Catalan数 && 【NOIP2003】出栈序列统计

    令h(1)=1, h(0)=1,catalan数满足递归式: h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)h(0) (n>=2) =C(2n, n)/(n+1) ...

  3. 卡特兰数 Catalan数 ( ACM 数论 组合 )

    卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1)  编辑 收藏 引用 所属分类: ACM ( 数论 ...

  4. 【集训笔记】【大数模板】特殊的数 【Catalan数】【HDOJ1133【HDOJ1134【HDOJ1130

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3324 http://blog.csdn.net/xymscau/artic ...

  5. catalan 数——卡特兰数(转)

    Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...

  6. Catalan数——卡特兰数

    一.Catalan数的定义 令h(0)=1,h(1)=1,Catalan数满足递归式:h(n) = h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)*h(0)  (n& ...

  7. (转载)Catalan数——卡特兰数

    Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...

  8. hdu 1130 How Many Trees?(Catalan数)

    How Many Trees? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. POJ 1095 Trees Made to Order 最详细的解题报告

    题目来源:Trees Made to Order 题目大意:根据下面的规则给一棵二叉树编号: 规则1:如果二叉树为空,则编号为0: 规则2:如果二叉树只有一个节点,则编号为1: 规则3:所有含有m个节 ...

随机推荐

  1. Android实习结束后的阶段性总结

    2015年4月14日即将实习结束,在过去的五六个月里,对于Android开发还是学到了很多,临走前将以前做的笔记整理一下,自己也再回顾一次.零散是必然的,也可能只是一小段代码片段,但都是曾经我在学An ...

  2. 5.SpringMVC 配置式开发-处理器适配器

    处理器适配器HandlerAdapter 1.SimpleControllerHandlerAdapter(默认) 所有实现了 Controller 接口的处理器 Bean,均是通过SimpleCon ...

  3. [react] - 循环请求 redux-saga

    //根据uuid 获取 apt报告信息 *getNotesByUid({ payload, callback }, { call, put }) { // payload 是个数组, 并发执行,参考r ...

  4. 运行tomcat7w.exe提示指定的服务未安装 解决办法

    一.问题重现点击bin下tomcat7w.exe出现如下提示:提示指定的服务未安装 二.原因分析tomcat7.exe和tomcat7w.exe要起作用必须先为这两个文件安装服务.其中tomcat7. ...

  5. STM32——CAN总线过滤器设置

    STM32CAN控制器每个筛选器组由两个32位的寄存器组成. 根据所需位宽的不同,各个筛选器可配置成16位或32位模式(如下图,当FSCx=1为32位模式,FSCx=0时为16位模式).同时,筛选器的 ...

  6. 阿里云MySQL用Navicat连接问题

    阿里云上装好MySQL用Navicat连接出现密码正确,Navicat连接测试失败.解决方案:网上众多方案,比如:放行3306端口啥子的,加入安全组啥子的.确认这些都没问题,还是出现密码正确,测试连接 ...

  7. Java中的集合(上):概述、Collection集合、List集合及其子类

    一.集合的体系结构 二.Collection集合 1.基本使用 如下代码 import java.util.ArrayList; import java.util.Collection; public ...

  8. org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]

    错误: 在 IDEA 创建WEB项目之后,打印出的日志中总是出现一行警告信息: 12-May-2018 15:52:30.692 警告 [RMI TCP Connection(3)-127.0.0.1 ...

  9. String类-StringBuffer类-StringBuilder类的比较

    package LC20130929; /**  * 字符串处理类: StringBuffer ~~ StringBuilder 〉〉 String   效果一样但是,性能却大不一样!         ...

  10. import this: python原则

    >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is ...