用memoization dp解。
用dp[n][k]来记录结点数为n,高度<=k的树的形态的个数。
由于树的结点的度数只可能为0或2,这个树的结点总数必然是个奇数。(推导很简单,一般数据结构书都会有,略)
树的高度最高为(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];
利用对称性质,可以节省一半计算。
dp[1][1]是递归的出口。
有了dp[n][k]了,求高度恰好等于k的树的形态的个数就很显然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;
}