Trees Made to Order
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 465 Accepted Submission(s): 271
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.
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.
個人理解:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define PB push_back
typedef long long ll;
const int maxn=500000000;
vector<ll> sum,tree;
void init() {
sum.PB(0);
tree.PB(1);
while(*sum.rbegin()<maxn) {
tree.PB(0);
for(int i=0;i<tree.size()-1;i++)
*tree.rbegin()+=tree[i]*tree[tree.size()-i-2];
sum.PB(*sum.rbegin()+*tree.rbegin());
}
}
void dfs(int p) {
if(!p)
return ;
int m=lower_bound(sum.begin(),sum.end(),p)-sum.begin();
p-=sum[m-1];//該棵樹在相同節點數的樹中的序數
int k=0,lp=1,rp;
while(p>tree[m-1-k]*tree[k]&&m-1-k-1>=0) {
p-=tree[m-1-k]*tree[k];
k++;
}//求左子樹節點數
if(k) {
while(p>tree[m-1-k]) {
p-=tree[m-1-k];
lp++;
}
lp+=sum[k-1];//左子樹序數
printf("(");
dfs(lp);
printf(")");
}
printf("X");
if(m-1-k) {
rp=p+sum[m-1-k-1];//右子樹序數
printf("(");
dfs(rp);
printf(")");
}
}
int main() {
init();
int n;
while(cin >> n,n) {
dfs(n);
cout << endl;
}
return 0;
}