zoukankan      html  css  js  c++  java
  • 【BZOJ 3769】【spoj 8549】BST again

    问题描述

    求有多少棵大小为n的深度为h的二叉树。(树根深度为0;左右子树有别;答案对1000000007取模)

    输入格式

    第一行一个整数T,表示数据组数。 以下T行,每行2个整数n和h。

    输出格式

    共T行,每行一个整数表示答案(对1000000007取模)

    样例输入

    2

    2 1

    3 2

    样例输出

    2

    4

    数据范围

    对于100%的数据,1≤n≤600,0≤h≤600,1≤T≤10

    题解

    f[i][j]表示大小为i,深度不超过j的树的个数

    除去根节点,子树中还有i-1个节点,枚举左右子树的节点数,乘法原理相乘

    f[i][j]=f[i-k-1][j-1]+f[k][j-1] (0≤k<i)

    边界条件,当i==0时,由于乘法的需要,f[0][j]=1;当j==0时,当且仅当i==1时存在一个二叉树,f[i][0]=(i==1)

    如果用记忆化搜索,i==0的条件必须写在j==0前面,因为j==0的条件后还有i==1的条件,不满足这个条件,还有i≠0的条件,包含了i==0的条件(有点绕?)

     1 #include <cstdio>
     2 const int maxn=1000000007;
     3 int T,n,h,f[605][605],ans;
     4 int dp(int i,int j)  
     5 {
     6     if (i==0) return 1;
     7     if (j==0) return i==1;
     8     if (f[i][j]) return f[i][j]; 
     9     for (int k=0;k<i;k++)
    10       f[i][j]=(f[i][j]+1ll*dp(i-k-1,j-1)*dp(k,j-1)%maxn)%maxn; 
    11     return f[i][j];
    12 } 
    13 int main()
    14 {
    15     int i,j,k;
    16     scanf("%d",&T);
    17     while (T--)
    18     {
    19         scanf("%d%d",&n,&h);
    20         ans=dp(n,h)-dp(n,h-1);
    21         while (ans<0) ans+=maxn;
    22         printf("%d
    ",ans);
    23     }
    24     return 0;
    25 }
  • 相关阅读:
    Spark高可用集群搭建
    Promise
    Redux 检测状态树变更
    React forwardRef:跳转引用
    React createRef:引用
    Git 分支合并:合并某次提交
    Eclipse 创建Android 模拟器失败:no cpu/abi system image available for this target
    Eclipse Android 模拟器启动过慢
    Mac Eclipse 配置 SDK Manager Proxy (代理)
    Mac 安装、卸载JDK 1.6
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9881278.html
Copyright © 2011-2022 走看看