0
点赞
收藏
分享

微信扫一扫

2017年第0届浙江工业大学之江学院程序设计竞赛决赛—M


Problem M: qwb与二叉树


Time Limit: 1 Sec  Memory Limit: 128 MB

Submit: 105  Solved: 16

[​​Submit​​​][​​Status​​​][​​Web Board​​]

Description


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



Input


多组输入,处理到文件结束,大约有104组数据。
每一组输入一行,两个正整数n,m(1≤m≤n≤50),意义如题目所述。


Output


每一行输出一个数,表示相应询问的答案,由于答案可能很大,请将答案对109+7取模后输出。


Sample Input

4 2

10 5

Sample Output

6

252

HINT


样例1的6种形态: 





 


【分析】 比赛的时候一直以为自己模拟错了...我也不知道为什么一直以为自己模拟错了...最后10min的时候发现自己模拟的是对的...都不知道当时发生了什么..... 有一道经典面试题是问有n个节点的二叉树有多少种不同的形态 那么用递归的方式可以考虑出: 当节点只有1个的时候,f(1)=1; 当节点只有2个的时候,f(2)=f(1)*f(0)+f(0)*f(1) 当节点只有3个的时候,f(3)=f(2)*f(0)+f(1)*f(1)+f(0)*f(2) //以一个点为根,它的左子树和右子树所有节点数的所有可能性 类推可以得到f(n)=f(n-1)f(0)+f(n-2)f(1)+……….+f(1)f(n-2)+f(0)f(n-1)  //这里这个公式刚好是卡特兰数... —————— 如果能理解上面的推导,那这道题无非就是在上面的推导过程中增加一个叶子数 f[i][j]表示节点有i个,叶子有j个的状态数 那么状态转移就直接转移就可以了....f[i][j]可以从上面的每个子树情况中计算所有叶子数加起来为j的状态数... 【代码】

#include <stdio.h>
#define MOD 1000000007
long long f[60][60]={0};
int main()
{
f[0][0]=f[1][1]=1;
f[2][1]=2;
for (int i=3;i<=50;i++)
for (int j=1;j<i;j++)
{
int x=0,y=i-1;
for (;x<y;x++,y--)
{
for (int k=0;k<=j;k++)
f[i][j]=(f[i][j]+2*((f[x][k]*f[y][j-k])%MOD)%MOD)%MOD;
}
if (x==y)
{
for (int k=0;k<=j;k++)
f[i][j]=(f[i][j]+(f[x][k]*f[y][j-k])%MOD)%MOD;
}
}
int n,m;
while (~scanf("%d%d",&n,&m))
{
printf("%lld\n",f[n][m]);
}
return 0;
}




举报

相关推荐

0 条评论