Combinatorics——HDUOJ 1100
来源:互联网 发布:fifaol3 超玩数据库 编辑:程序博客网 时间:2024/05/21 10:51
原题:
Problem 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
0Sample Output
X
((X)X(X))X
(X(X(((X(X))X(X))X(X))))X(((X((X)X((X)X)))X)X)
要搞懂这道题,首先需要了解二叉树和卡特兰数Catalan:
卡特兰数传送门:
http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html(帖子)
https://baike.baidu.com/item/%E5%8D%A1%E7%89%B9%E5%85%B0%E6%95%B0/6125746?fr=aladdin(百度百科)
代码参考:http://www.cnblogs.com/jackge/archive/2013/05/19/3086526.html
卡特兰数 类似题目:http://blog.csdn.net/hackbuteer1/article/details/7450250
解题思路:
根据下面的规则给一棵二叉树编号:
- 如果二叉树为空,则编号为0;
- 如果二叉树只有一个节点,则编号为1;
- 所有含有m个节点的二叉树的编号小于所有含有m+1个节点的二叉树的编号;
- 如果一棵含有m个节点的二叉树(左子树为L,右子树为R)的编号为n,要想其它含有m个节点的二叉树的编号如果大于n,则需要满足两个条件中的任意一个:
- 1、左子树的编号大于L的编号;
- 2、左子树的编号等于L的编号,但是右子树的编号大于R的编号。
代码:
#include <stdio.h>long long C[21] = { 1 };//第21个卡特兰数达到65亿void Catalan()//预处理卡特兰数{ int i = 1; for (; i <= 20; i++) { C[i] = C[i - 1] * (4 * i - 2) / (i + 1); }}void PrintfAnswer(int n, long long rank)//输出n个节点中,排序第rank的二叉树{ if (n == 1)//只有1个节点 { printf("X"); return; } if(rank <= C[n - 1])//排名靠前,即没有根节点没有左子树 { printf("X"); printf("("); PrintfAnswer(n - 1, rank); printf(")"); }else if(rank >= C[n] - C[n - 1] + 1)//排名靠后,即没有根节点没有右子树 { printf("("); PrintfAnswer(n - 1, rank - (C[n] - C[n - 1])); printf(")"); printf("X"); }else { int t = n - 2; long long temp; long long ExceptLeftAllTree = C[n] - C[n - 1];//根节点除了只有左子树外,一共还有的树的种类(包括只有右子树) int LeftTreeNum; int RightTreeNum; long long NewRank;//找出的新的种类的树中的排序(求出左右子树数量的 该种类 中的排序) for (int i = t; i >= n - 1 - t; i--)//i为根节点左子树数量 { temp = C[i] * C[n - 1 - i];//例如:若n = 5,则C[3]*C[1](即左子树为3,右子树为1的类型有temp种) if (rank > ExceptLeftAllTree - temp)//检测是否符合左子树为i,又右子树为n-1-i { LeftTreeNum = i; break; }else { ExceptLeftAllTree -= temp; } } //求出左右子树各多少之后,算出在该类型树中的排序NewRank NewRank = rank - (ExceptLeftAllTree - temp); RightTreeNum = n - LeftTreeNum - 1; printf("("); long long LeftTreeRank;//左子树中的排序 //这个地方需要注意:右子树的优先级是小于左子树的,所以每次判断子数中的排序时,注意左子树每变换一次,右子数变换C[RightTreeNum]次 if(NewRank < C[RightTreeNum])//注意排序 { LeftTreeRank = 1; }else if(NewRank % C[RightTreeNum] == 0) { LeftTreeRank = NewRank / C[RightTreeNum]; }else { LeftTreeRank = NewRank / C[RightTreeNum] + 1; } PrintfAnswer(LeftTreeNum, LeftTreeRank); printf(")X("); long long RightTreeRank;//右子树中的排序 if(NewRank % C[RightTreeNum] == 0) { RightTreeRank = C[RightTreeNum]; }else { RightTreeRank = NewRank % C[RightTreeNum]; } PrintfAnswer(RightTreeNum, RightTreeRank); printf(")"); }}int main(){ int i; long long n; int c; Catalan();//预处理卡特兰数 while (scanf("%lld",&n)!=EOF && n) { for (i = 1;;i++) { if (n > C[i]) { n -= C[i];//求出在当前节点所有排序中的名次 }else { c = i;//求出当前是i节点组成的二叉树 break; } } PrintfAnswer(c, n); printf("\n"); } return 0;}
- Combinatorics——HDUOJ 1100
- Combinatorics——HDUOJ 1027
- Combinatorics——HDUOJ 1085
- Combinatorics——HDUOJ 1171
- Combinatorics——HDUOJ 1261
- Combinatorics——HDUOJ 1398
- Combinatorics——HDUOJ 1028
- Combinatorics——HDUOJ 1294
- Combinatorics——HDUOJ 1465
- Combinatorics——HDUOJ 1492
- Combinatorics——HDUOJ 1510
- Combinatorics——HDUOJ 1521
- Combinatorics——HDUOJ 2110
- hduoj 4196 ——Remoteland
- BigNums——HDUOJ 1002
- BigNums——HDUOJ 1042
- BigNums——HDUOJ 1047
- BigNums——HDUOJ 1063
- M600(A3)云台+妙算manifold视频读取
- 欢迎使用CSDN-markdown编辑器
- osmdroid API解读(七)
- 第八周【项目3-顺序串算法】
- Java代码实现两台电脑之间传文件(2)
- Combinatorics——HDUOJ 1100
- 第七周项目一—建立顺序环形队列算法库
- NOIP 2017.10.24 总结+心得
- Android使用无线连接手机调试
- Go实现图的宽度搜索
- Spring-IOC
- 对KMP算法的理解
- EXT.NET
- 病毒式营销