被这到题小郁闷了一下,终于AC了,郁闷人的要点说到底是数数的问题,从哪数,数到哪,算几?
AC率高的有两种,一种是真的太简单,sample数据覆盖广,另一种是这道题,好不容易AC了,赶紧再多来几遍看看能不能少用些时间或memory。1062高达63%的AC率,但却是道稍有难度的题,主要是中间算每段的起始和子树的节点数和入口编号有些琐碎。
题目算法
先说明一下,关于递归函数的参数,我也在网上搜到看了别人的程序,有使用单独一个参数就是编号本身的,这个当然很好,尤其是看起来程序非常清晰,不过就是能得出子树的编号,说明也已经得到它的节点数目m以及它是有m个节点的树中的第几个。。。所以干脆还是传节点数目m和它在m个节点的树中的名次。
废话不说了,算法如下:
1。首先计算出所有含有m个节点的树的总数目,存在idex[m]里,这一步我是先写过程序算出按照题目的要求,节点数不会超过18,并且手动把结果存在程序里了。idex[0]=1。这个程序应该很好些的,就不详细说了。
2。算出输入数字的节点数目及其名次,调用递归函数void gettree(int node, long bit).
3。在递归函数中,从i=0开始,逐次执行temp -= idex[i] * idex[node-1-i];,直到temp<=0,这时恢复temp最后一次大于0的值。
讲到这里,先给个例子,比如题中有图的20,那么20-1-2-5=12,这时再减14就为负所以20有4个节点,除去根节点,还剩3个节点,3个节点分配顺序由小到大为:
1 2---idex[1]*idex[2] = 1*2 = 2
2 1---idex[2]*idex[1] = 2*1 = 2
3 0---idex[3]*idex[0] = 1*2 = 5
这时12-5=7,7-2=5,5-3=2,2-5<0,所以这3个节点的分配为左3右0。
4。知道了左右子树的节点分配,也就知道了左右子树各能产生多少种可能,利用乘法原理。
这时剩下的数字代表第几位。。。所以减1然后处以右子树的可能组合数idex[node-1-i],又因为除下来的数又是从0开始数,所以再加1,于是就是:
x = ((temp-1)/idex[node-1-i])+1,这是左子树在节点为i个时的入口编号,接下来求得最后剩余的数字,
y = temp-(x-1)*idex[node-1-i];,这是右子树在节点为node-1-i个时的入口编号。
(这里的node指得是当前整个树的节点数目)
5。接下来调整相应的输出格式,递归,结束条件是node==1,输出X。
程序清单如下
#include < stdio.h >
long idex[ 19 ];
long in ;
void gettree( int node, long bit)
{
if ( 1 == node)
{
printf( " X " );
}
else
{
long temp = bit;
int i;
for (i = 0 ;i < node;i ++ )
{
temp -= idex[i] * idex[node - 1 - i];
if (temp <= 0 )
break ;
}
temp += idex[i] * idex[node - 1 - i];
long x,y;
x = ((temp - 1 ) / idex[node - 1 - i]) + 1 ;
y = temp - (x - 1 ) * idex[node - 1 - i];
if ((node - 1 - i > 0 ) && (i > 0 ))
{
printf( " ( " );
gettree(i,x);
printf( " )X( " );
gettree(node - 1 - i,y);
printf( " ) " );
}
else if (i > 0 )
{
printf( " ( " );
gettree(i,x);
printf( " )X " );
}
else
{
printf( " X( " );
gettree(node - 1 - i,y);
printf( " ) " );
}
}
}
void solve()
{
long temp = in ;
int i;
for (i = 1 ;;i ++ )
{
temp -= idex[i];
if (temp <= 0 )
break ;
}
temp += idex[i];
gettree(i,temp);
printf( "/n " );
}
int main()
{
// freopen("1062.txt","r",stdin);
idex[ 0 ] = 1 ;
idex[ 1 ] = 1 ;
idex[ 2 ] = 2 ;
idex[ 3 ] = 5 ;
idex[ 4 ] = 14 ;
idex[ 5 ] = 42 ;
idex[ 6 ] = 132 ;
idex[ 7 ] = 429 ;
idex[ 8 ] = 1430 ;
idex[ 9 ] = 4862 ;
idex[ 10 ] = 16796 ;
idex[ 11 ] = 58786 ;
idex[ 12 ] = 208012 ;
idex[ 13 ] = 742900 ;
idex[ 14 ] = 2674440 ;
idex[ 15 ] = 9694845 ;
idex[ 16 ] = 35357670 ;
idex[ 17 ] = 129644790 ;
idex[ 18 ] = 477638700 ;
while (scanf( " %ld " , & in ) != EOF && in > 0 )
solve();
// fclose(stdin);
return 0 ;
}