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;
- }