UVA 10312 - Expression Bracketing(数论+Catalan数)
2016-02-04 18:02
369 查看
题目链接:10312 - Expression Bracketing
题意:有n个x,要求分括号,推断非二叉表达式的个数。思路:二叉表达式的计算方法就等于是Catalan数的,那么仅仅要计算出总数,用总数减去二叉表达式个数。得到的就是非二叉表达式的个数。
那么计算方法是什么呢。
看题目中的图,对于n = 4的情况,能够分为这几种情况来讨论:
四个1。 一个2两个1,一个3一个1。一个4。相应的情况数为1。3。 2。 1。
答案为f(1)^4 + 3 * f(2) * f(1)^2 + f(3) * f(1) + f(4)。
一种做法是把n去分解然后计算。可是显然这是不可行的,n最大为26,情况数太多了。
然后找题解,发现这个竟然有公式,这个式子叫SuperCatalan数。
然后也有递推出来的解。设dp
[2]。n表示还有n个子节点未分配。2表示0为最多分配n - 1个点,1为最多分配n个点,这样能保证子树都至少有两个节点。这样就是总情况了,直接用记忆化搜下去就可以
代码:
公式解:
#include <stdio.h> #include <string.h> int n; long long Catalan[30], SuperCatalan[30]; int main() { Catalan[1] = Catalan[2] = 1; for (int i = 3; i <= 26; i++) { Catalan[i] = Catalan[i - 1] * (4 * i - 6) / i; } SuperCatalan[1] = SuperCatalan[2] = 1; for (int i = 3; i <= 26; i++) { SuperCatalan[i] = (3 * (2 * i - 3) * SuperCatalan[i - 1] - (i - 3) * SuperCatalan[i - 2]) / i; } while (~scanf("%d", &n)) { printf("%lld\n", SuperCatalan - Catalan ); } return 0; }
递推解:
#include <stdio.h> #include <string.h> int n; long long Catalan[30], dp[30][2]; long long dfs(int n, int flag) { long long &ans = dp [flag]; if (~ans) return ans; if (n <= 1) return ans = 1; ans = 0; for (int i = 1; i < n + flag; i++) ans += dfs(i, 0) * dfs(n - i, 1); return ans; } int main() { Catalan[1] = Catalan[2] = 1; for (int i = 3; i <= 26; i++) { Catalan[i] = Catalan[i - 1] * (4 * i - 6) / i; } while (~scanf("%d", &n)) { memset(dp, -1, sizeof(dp)); printf("%lld\n", dfs(n, 0) - Catalan ); } return 0; }
相关文章推荐
- 弄了一个支持SSL的TCP客户端
- 编程巨星的唯一秘诀
- request.getParameter("Name")
- canvas之二绘图绘图详解曲线,文字,高级应用
- memcached—如何在Windows操作系统中安装、启动和卸载memcached
- iOS之无法隐藏statusbar
- TextView设置drawable
- 使用R画地图数据
- JavaScript总结(二) 系统分析
- 合并svn分支到主干(linux)
- Fast Paxos 分布式算法
- 文字图标
- STM32 USB学习笔记1
- Access query 使用方法
- win7下安装ubuntu14.04双系统问题总结
- SVM: 用kernels(核函数)来定义新的features,避免使用多项式,高斯kernel
- hdu 2199 Can you solve this equation?
- Javascript中的new
- poj1321 简单dfs
- Android Studio常见错误