长沙理工大学第十二届ACM大赛-重现赛 K - 大家一起来数二叉树吧

题目描述

某一天,Zzq正在上数据结构课。老师在讲台上面讲着二叉树,zzq在下面发着呆。
突然zzq想到一个问题:对于一个n个节点,m个叶子的二叉树,有多少种形态呐?你能告诉他吗?
对于第一组样例的解释
 

输入描述:

每一组输入一行,两个正整数n,m(n<=50)意义如题目

输出描述:

每一行输出一个数,表示相应询问的答案取模1000000007
示例1

输入

4 2
10 5

输出

6
252

备注:

a取模b等于a%b,即a除以b的余数

题解

$dp$。

$dp[i][j]$表示有$i$个节点,$j$个叶子节点的不同二叉树的形态。

对于$dp[i][j]$,我们可以枚举根节点左子树的节点个数$x$和叶子节点个数$y$,将$dp[x][y] * dp[i-1-x][j-y]$累加就可以得到$dp[i][j]$了。

#include <bits/stdc++.h>
using namespace std;

long long mod = 1e9 + 7;
long long dp[60][60];
int n, m;

int main() {
  dp[0][0] = 1;
  dp[1][1] = 1;
  for(int i = 2; i <= 50; i ++) {
    for(int j = 1; j <= i - 1; j ++) {
      dp[i][j] = 0;
      for(int x = 0; x <= i - 1; x ++) {
        for(int y = 0; y <= x; y ++) {
          if(j - y < 0) continue;
          long long sum = dp[x][y] * dp[i - 1 - x][j - y] % mod;
          dp[i][j] = (dp[i][j] + sum) % mod;
        }
      }
    }
  }
  while(~scanf("%d%d", &n, &m)) {
    printf("%lld\n", dp[n][m]);
  }
  return 0;
}

  

posted @ 2017-12-26 21:51  Fighting_Heart  阅读(275)  评论(0编辑  收藏  举报