二叉树dp,一般两种分类思路:
1、分层
2、分左右子树
这种分类方法是不是很熟悉?对,我们遍历二叉树也是这样的思路。这里我使用了分左右子树行态进行讨论的方法来递归。
根据题目,记拥有k个层、n个节点的所求树有(k,n)种行态。那么只有2*K-1 <=N && N <= upper[K]-1且N为奇数的时候有解。
画一画基本情况:
(1,1) = 1
(2,3) = 1
(3,5) = 2; (3,7) = 1
研究第四层,可以发觉 (4,7)分左右子树可以看成(4,6+1),那么只要把6分出去、并且保证分完还是4层就可以;要保持4层,一个分出去的就必须是(3,?)。于是得到递推式:
(k,n) = (k,n-1 + 1) = sum_t (k-1,m) + (t, n - 1 -ml)
其中m为[2*(k-1) - 1, 2^{k-1}-1]中的奇数,t为所在数对拥有第二坐标为n-1-m的任何第一坐标。
题目要取模,别忘了取模。
用数组存然后如上递推的话,需要四层循环:一层是递推给k的,二层是给k对应n的,三层是找l,四层是找m。
这里关于循环上界,并不需要算pow(2,*),因为我们要求的N是给出的,而需要的第二维数字不需要比N大,所以构造循环。关键代码如下:
for(int k = 4;k <= K;k ++)
{
for(int n = 2*k - 1;n <=N ;n += 2)
{
for(int m = 2*(k-1) - 1;m<=n-2; m +=2)
{
for(int t = 1;t <=k-1;t ++)
{
if(a[t][n-1-m]!=0)
{
if(t != k - 1)
a[k][n] += a[k-1][m]*a[t][n-1-m]*2%MODULO;
else
a[k][n] += a[k-1][m]*a[t][n-1-m]%MODULO;
}
}
}
a[k][n] = a[k][n]%MODULO;
}
}