10. 家谱

题目描述

在某个家谱中,每人都生两个儿子。这些人之间的关系可以用二叉树来表示。这些二叉树总共有N个节点(3 <= N < 200)。这些二叉树有如下性质:
每一个结点的度是0或2。度是这个结点的儿子的数目。

树的高度等于K(1 < K < 100)。高度是从根到任何叶子的最长的路径上的结点的数目。有多少不同的家谱结构? 如果一个家谱的树结构不同于另一个的, 那么这两个家谱就是不同的。输出家谱树的个数除以9901之后的余数。

输入:
两个空格分开的整数, N和K。
输出:
一个整数,表示家谱树的个数除以9901之后的余数。

提示:
有5个结点,高为3的两个不同的家谱:

          @                @      
         / \              / \
        @   @     和     @   @
       / \                  / \
     @   @                 @   @

测试用例

输入

5 3

输出

2

分析

参考:http://www.cnblogs.com/geek-007/p/7237010.html
代码

#include<iostream>

using namespace std;

int MOD = 9901, f[202][202] = { 0 }, g[202][202] = { 0 };

int main()
{
    int m, n;
    while (~scanf("%d %d", &n, &m))
    {
        f[1][1] = g[1][1] = 1;
        for (int j = 2; j <= m; j++)
            g[1][j] = 1;
        for (int i = 3; i <= n; i++)
        {
            for (int j = 2; j <= m; j++)
            {
                for (int k = 1; k < i; k++)
                {
                    f[i][j] = (f[i][j] + f[k][j - 1] * g[i - k - 1][j - 2] * 2 % MOD) % MOD;
                    f[i][j] = (f[i][j] + f[k][j - 1] * f[i - k - 1][j - 1] % MOD) % MOD;
                }
                g[i][j] = (g[i][j - 1] + f[i][j]) % MOD;
            }
        }

        printf("%d\n", f[n][m]);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值