不错的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;
}