博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[JZOJ6353] 【NOIP2019模拟】给
阅读量:5291 次
发布时间:2019-06-14

本文共 950 字,大约阅读时间需要 3 分钟。

题目大意

对于所有的整数\(k \in [1,n]\),求叶子结点有\(k\)个的二叉树个数,满足每个非叶子结点都有两个儿子,并且对于每个叶子结点,从根节点到它经过的向左的边数少于等于\(m\)个。


思考历程

很容易推出这样的\(DP\)

\(f_{i,j}\)表示\(m=i\)\(n=j\)的答案是多少。
\(f_{i,j}=\sum_{k \in [1,n)}{f_{i-1,k}f_{i,j-k}}\)
这样当然过不了。
然而,如果只看第二维,就会感觉它和卡特兰数长得很像。
于是就往打表的方面想……
打出一个表,表可以分成上下两个三角形,下面的那个三角形就是标准的卡特兰数……
然而找不到上面的规律。
%%%GMH大佬居然找到了。
于是就暴力了……


正解

换一种思路\(DP\)

\(f_{i,j}\)表示已经放了\(i\)个节点,从根往下走已经向左走了\(j\)次。
有两种转移:
一个是继续向左走,那就是转移到\(f_{i+1,j+1}\)
另一个是回到第一个左转的地方,放一个右儿子,那就是转移到\(f_{i+1,j-1}\)
很显然放的节点个数为\(2k-1\),所以这个方法是能过的。


代码

using namespace std;#include 
#include
#include
#define N 5010#define mo 998244353#define ll long longint m,n;ll f[N*2][N];int main(){ freopen("ca.in","r",stdin); freopen("ca.out","w",stdout); scanf("%d%d",&m,&n); f[1][0]=1; for (int i=1;i<2*n-1;++i) for (int j=0;j

总结

在做树一类的\(DP\)的时候,不要仅仅是想着从下往上转移,还要考虑一下按照\(dfs\)序来转移。

转载于:https://www.cnblogs.com/jz-597/p/11535406.html

你可能感兴趣的文章
深入理解HTTP Session
查看>>
【转载】uclibc和glibc的差别
查看>>
搭建《深入Linux内核架构》的Linux环境
查看>>
Yuchuan_Linux_C 编程之三 静态库的制作和使用
查看>>
C#的最实用的的字符串加密解密方法大全
查看>>
前台通过window.localStorage存储用户名
查看>>
基于Flutter实现的仿开眼视频App
查看>>
析构器
查看>>
驱动的本质
查看>>
Swift的高级分享 - Swift中的逻辑控制器
查看>>
https通讯流程
查看>>
Swagger简单介绍
查看>>
C# 连接SQLServer数据库自动生成model类代码
查看>>
关于数据库分布式架构的一些想法。
查看>>
BigDecimal
查看>>
Python语法基础之DataFrame
查看>>
Python语法基础之对象(字符串、列表、字典、元组)
查看>>
大白话讲解 BitSet
查看>>
sql语句中where与having的区别
查看>>
Python数据分析入门案例
查看>>