不錯的DP題。設dp[i][j]表示 i個點組成的等於k高度的滿足題意的個數,這樣高度要求是k的就直接引用,後面的應該不用說了吧。任何高度爲Hi的樹都是兩個子樹構成,一個必須高度爲Hi-1,另外一個無所謂。
但是要注意重複。注意代碼註釋部分。
/*
ID: fairyroad
TASK:nocows
LANG:C++
*/
#include<fstream>
using namespace std;
ifstream fin("nocows.in");
ofstream fout("nocows.out");
unsigned long dp[201][101];
unsigned long N, K;
inline unsigned long MAX(unsigned long a, unsigned long b){ return a > b ? a : b;}
int main()
{
fin>>N>>K;
unsigned long res = 0;
unsigned long i, j;
unsigned long p, q;
dp[1][0] = 1;
dp[1][1] = 1;
for(i = 3; i <= N; i+=2) // dynamic programming
{
unsigned long upper = i>>1;
for(j = 1; j <= upper ; j+=2) // enumerating sub-tree, j : number of nodes
{
for(p = 1; p <= dp[j][0]; ++p) // traversing various sub-tree's height
{
for(q = 1; q <= dp[i-1-j][0]; ++q)
{
if(dp[j][p] && dp[i-1-j][q])
{
unsigned long height = MAX(p, q)+1;
if(height > dp[i][0])
dp[i][0] = height;
res = (dp[j][p]*dp[i-1-j][q])<<1; // 直接翻轉
if(i-1-j == j) // 防止重複
res>>=1;
dp[i][height] = (dp[i][height]+res)%9901;
}
}
}
}
}
fout<<dp[N][K]%9901<<endl;
return 0;
}