用memoization dp解。
用dp[n][k]來記錄結(jié)點數(shù)為n,高度<=k的樹的形態(tài)的個數(shù)。
由于樹的結(jié)點的度數(shù)只可能為0或2,這個樹的結(jié)點總數(shù)必然是個奇數(shù)。(推導(dǎo)很簡單,一般數(shù)據(jù)結(jié)構(gòu)書都會有,略)
樹的高度最高為(n-1)/2。
dp[n][k]= dp[1][k-1]*dp[n-2][k-1]+dp[2][k-1]*dp[n-3][k-1]+...+dp[n-2][k-1]*dp[1][k-1];
利用對稱性質(zhì),可以節(jié)省一半計算。
dp[1][1]是遞歸的出口。
有了dp[n][k]了,求高度恰好等于k的樹的形態(tài)的個數(shù)就很顯然dp[n][k]-dp[n][k-1]可得。
由于要模上9901,注意可能是負值,所以要先加上9901再求模。
代碼如下:
#include?<iostream>
#include?<fstream>
using?namespace?std;
ifstream?fin("nocows.in");
ofstream?fout("nocows.out");
int?dp[200][100];
int?n,k;
int?ped_num(int?node,int?height);
void?solve()
{
????memset(dp,-1,sizeof(dp));
????dp[1][1]?=?1;
????in>>n>>k;
????out<<(ped_num(n,k)-ped_num(n,k-1)+9901)%9901<<endl;
}
int?ped_num(int?node,int?height)
{
????if(node%2!=1)?return?0;
????if(height>(node+1)/2)
????????height?=?(node+1)/2;
????if(dp[node][height]!=-1)
????????return?dp[node][height];
????int?res?=?0;
????for(int?i=1;i<(node-1)/2;i+=2){
????????res+=ped_num(i,height-1)*ped_num(node-1-i,height-1);
????????res%=9901;
????}
????res*=2;
????int?tmp?=?ped_num((node-1)/2,height-1);
????res+=tmp*tmp;
????res%=9901;
????dp[node][height]?=?res;
????return?res;
}
int?main(int?argc,char?*argv[])
{
????solve();?
????return?0;
}