题目描述
农民约翰准备购买一群新奶牛。 在这个新的奶牛群中, 每一个母亲奶牛都生两小奶牛。这些奶牛间的关系可以用二叉树来表示。这些二叉树总共有 N ( 3 ≤ N ≤ 200 ) N(3\le N\le 200) N(3≤N≤200) 个节点。这些二叉树有如下性质:
有多少不同的家谱结构?如果一个家谱的树结构不同于另一个的,那么这两个家谱就是不同的。
输出可能的家谱树的个数除以 9901 9901 9901 的余数。
输入格式
一行两个正整数 n , k n,k n,k ,含义见题面。
输出格式:
一行一个非负整数,表示不同的家谱结构的数目除以 9901 9901 9901 的余数。
数据范围与约定
对于 100 % 100\% 100%的数据, n ≤ 200 , k ≤ 100 n\le 200,k\le 100 n≤200,k≤100 。
f ( i , j ) f(i,j) f(i,j) 表示有 i i i 个节点,深度 不超过 j j j ,能够形成的家谱树的数量。
那么枚举左子树的节点个数 x x x (右字数节点数自然为 i − x − 1 i-x-1 i−x−1 ),根据乘法原理,有
f ( i , j ) = ∑ x = 0 i − 1 f ( x , j − 1 ) f ( i − x − 1 , j − 1 ) f(i,j)=\sum_{x=0}^{i-1}f(x,j-1)f(i-x-1,j-1) f(i,j)=x=0∑i−1f(x,j−1)f(i−x−1,j−1)
这是 O ( n 2 k ) \mathcal O(n^2k) O(n2k) 的,可以接受。但我们要求的不是 f ( n , k ) f(n,k) f(n,k) !
因为 f ( n , k ) f(n,k) f(n,k) 包含了深度为 1 1 1 到 k k k 的所有可能。我们想知道的是深度 恰好 为 k k k 的数量。那么多了个什么东西呢?深度为 1 1 1 到 k − 1 k-1 k−1 的数量。不正是 f ( n , k − 1 ) f(n,k-1) f(n,k−1) 吗?作差即可。
还有一些小细节,稍微提一下:
#include
const int M = 9901;
int dp[202][102];
int main(){
int n, k;
scanf("%d %d",&n,&k);
for(int j=1; j<=k; ++j){
dp[1][j] = 1;
for(int i=3; i<=n; i+=2)
for(int l=1; l<i-1; l+=2)
dp[i][j]=(dp[i][j]+dp[l][j-1]*dp[i-l-1][j-1])%M;
}
printf("%d\n",(dp[n][k]-dp[n][k-1]+M)%M);
return 0;
}