【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\n",ans);
23     }
24     return 0;
25 }

 

posted @ 2018-10-31 09:54  SAKURA12  阅读(151)  评论(0编辑  收藏  举报