被這到題小鬱悶了一下,終於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;
}