圣主的考验3810
(tree.cpp/pas)
【问题描述】
若对于二叉树 T 的每个节点 v,其左子树的高度L和右子树的高度R均满足|L–R|≤1,则这个树T有可能来自超自然之界。规定若某节点子树为空,则该子树的高度是0。你的任务是求有N个节点的可能来自超自然之界的树的数目。
【输入】
每个测试点包含若干个测试数据。
每个测试数据占一行,包含一个整数N。
输入文件以0结尾。
【输入】
对于每个测试数据,在单独的一行内输出结果。由于结果可能会很大,你只需要输出答案在十进制表示下的后九位。若答案不足九位,只需输出原答案。
【输入样例】
2
3
5
30
0
【输出样例】
2
1
6
11307920
【数据规模和约定】
对于30% 的测试点,N≤100。
对于70% 的测试点,N≤1000。
对于100% 的测试点,1≤N≤3000。
对于想到树型DP这个算法的难度还是不大的。
题解竟然说这道题的O(n^3)算法很简单?看不起蒟蒻也不至于这样吧??
这道题的树型DP确实是从来没见过啊..
设f[i][j]为有i个点,高度为j时的方案数,每次枚举左子树节点的个数,可得右子树节点的个数,通过如下方程进行递推:
if(h)//h是当前枚举高度
{
dp[i][h+1]+=dp[l][h]*dp[r][h-1];
dp[i][h+1]%=mod;
dp[i][h+1]+=dp[l][h-1]*dp[r][h];
dp[i][h+1]%=mod;
//满足|L-R|=1,拆开绝对值。
}
dp[i][h+1]+=dp[l][h]*dp[r][h];//满足|L-R|=0
dp[i][h+1]%=mod;
明显这个的复杂度为n(个点)*l(左子树)*h(高度),大概是O(n^3)
口也,n=3000!过不了怎么做?
口也,n=3000!打表啊!
..反正标程的神秘优化我是不想去看的,打表直接用这个DP即可!
注意初值:dp[0][0]=dp[1][1]=1;
跪给这个DP啊