动态规划问题
首先明确一下题目的意思:用N个点组成一棵深度为i的二叉树,求一共有几种方法?
设dp[i,j]表示用i个点组成深度最多为j的二叉树的方法数,则:
1.每个结点的度为偶数 2.该树有n个结点 3.该树的深度为k 问题分析: 用动态规划和乘法原理求解,可以观察到一个树G(有x个结点,深度为k),如果去除它的根结点可以得到两个子数G1,G2,这两个子图的深度为k-1,他们的结点数的和为x-1.设其中G1有i个结点则G2有x-1-i个结点.
定义P(G)为与满足条件的二叉树G有同样多结点有深度相同且同样满足条件的树的个数.
将二叉树按上述方法依次分解为(有1个结点,深度为k-1的树和有x-1-1个结点深度为k-1的树),(有2个结点,深度为k-1的树和有x-1-2个结点深度为k-1的树),(有3个结点,深度为k-1的树和有x-1-3个结点深度为k-1的树)...(有x-1-1个结点,深度为k-1的树和有1个结点深度为k-1的树)...
由乘法原理得到:由G按上述方法分解成的每对二叉树(Gx,Gy)加一个根结点构成的二叉树的个数有P(Gx)*P(Gy)个.
G可以分解为x-2对子树,由加法原理得到P(G)=∑P(Gi)*P(Gj){(i,j)∈G可以分解到的子树对(Gi,Gj)}
定义f(x,k)满足为深度为k,结点个数为x,每个结点的度为偶数的二叉树的个数,由上述分析得到dp(x,k)=∑(dp(x-1-i,k-1)*dp(i,k-1){1<=i<=x-2}.
注意:变乘边加边取模,在mod 9901 时,加上9901mod可避免出错。
/*
ID:xsy97051
LANG:C++
TASK:nocows
*/
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int dp[100][200];
int main()
{
int k,n;
freopen("nocows.in","r",stdin);
freopen("nocows.out","w",stdout);
cin>>n>>k;
for(int j=1;j<=k;++j)
dp[j][1]=1;
for(int j=1;j<=k;++j)
for(int i=3;i<=n;i+=2)
for(int k=1;k<=i-2;k+=2)
dp[j][i]=(dp[j][i]+dp[j-1][k]*dp[j-1][i-k-1])%9901;
cout<<(dp[k][n]-dp[k-1][n]+9901)%9901<<endl;
return 0;
}