UVA 10312 - Expression Bracketing(数论+Catalan数)

题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=1253">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[n][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[n] - Catalan[n]);
 	}
	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[n][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[n]);
 	}
	return 0;
}
时间: 2024-08-06 20:05:43

UVA 10312 - Expression Bracketing(数论+Catalan数)的相关文章

uva 10312 - Expression Bracketing(Catalan+SuperCatalan)

Set集合的配置 数据表的创建:表关系一个员工拥有多个身份 create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) ); create table CERTIFICATE ( id INT NOT NULL aut

UVa 10312 - Expression Bracketing

题目:求n个元素构成的树中,不是二叉树的个数. 分析:组合,计数,卡塔兰数. n个元素组成的二叉树的个数为卡塔兰数Cn-1:有如下递推关系: n个元素组成的所有树的个数为超卡塔兰数Sn:有如下递推关系: 卡特兰数参考:http://blog.csdn.net/mobius_strip/article/details/39229895 超卡塔兰数参考:http://mathworld.wolfram.com/SuperCatalanNumber.html 输出S(n)- C(n-1)即可. 说明:

【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到Catalan数,但是我却花了两个小时去找递推式. 首先 Catalan数 : 基本规律:1,2,5,14,42,132,.......... 典型例题: 1.多边形分割.一个多边形分为若干个三角形有多少种分法. C(n)=∑(i=2...n-1)C(i)*C(n-i+1) 2.排队问题:转化为n个人

uva 11105 - Semi-prime H-numbers(数论)

题目链接:uva 11105 - Semi-prime H-numbers 题目大意:H-number为4?k+1(k为非负数),H-composites为因子中含有H-number(不包括自己本身)的数,反之久是H-prime,给定n,求有多少H-composites. 解题思路:首先用筛选法求出范围内的H-prime,然后枚举两个判断乘积是否在范围内. #include <cstdio> #include <cstring> const int maxn = 1e6+5; ty

uva 11728 - Alternate Task(数论)

题目链接:uva 11728 - Alternate Task 题目大意:给出S,求N,要求N所有的因子和为S. 解题思路:枚举因子i,所有整除i的数和加上i. #include <cstdio> #include <cstring> const int N = 1005; int n, c[N], v[N]; void init () { memset(c, 0, sizeof(c)); memset(v, -1, sizeof(v)); for (int i = 1; i &l

UVA 10413 - Crazy Savages(数论)

UVA 10413 - Crazy Savages 题目链接 题意:一个岛上有一些山洞,有n个幸存者,每个幸存者初始在山洞Ci,山洞是形成一个环的,每天每个人都会走Pi,然后Li天后该人会死掉,要求一个最小的山洞数使得每个人在活着的时候都不会碰面(因为碰面就会发生冲突) 思路:枚举山洞数m,然后两两判断会不会碰面 判断的方法是:两个人其实就是两个线性方程 (c1+p1k1)%m=x 和 (c2+p2k2)%m=x 如果两人会在同一天碰面,那么两人k值相同,两式相减后得到(c1?c2)+k(p1?

uva 1341 - Different Digits(数论+bfs)

题目链接:uva 1341 - Different Digits 题目大意:给定一个数字n,要求求一个数字m,m可以整除n,并且尽量组成的数字种类(0~9)尽量少,在种类相同的情况下数值尽量小. 解题思路:可以证明两种数字肯定可以组成m,假设有数字k,一种数字可以有k,kk,kkk,kkkk,-整除n剩的数一定在0~n-1之间,所以肯定存在两个由k数字组成的数字同模,那么这两个数相减所得到的数即使kkk00000,两种数字.于是肯定了范围,枚举数字,然后用bfs获取答案,维护最小值即可. #in

uva 11538 - Chess Queen(数论)

题目链接:uva 11538 - Chess Queen 题目大意:在一个n?m的棋盘上,放两个皇后,要求两个皇后可以互相攻击,求有多少种放法. 解题思路:因为皇后的攻击范围为竖线.横线和斜线,所以枚举每条上两个皇后放的位置,比如一条斜线有8个,那么放两个皇后的种数就有C(82)种. 行数n,每行m个位置C(m2)?n 列数m,每列n个位置C(n2)?m 斜线,2?(2?∑i=1n?1i?(i?1)+(m?n+1)?n?(n?1)),因为正斜线和翻斜线,所以要乘以2 最后公式化简为2?n?(n?

uva 10726 - Coco Monkey(数论)

题目链接:uva 10726 - Coco Monkey 题目大意:n个人,m只猴子,l和r,表示上下限.找出l~r之间有几个数满足题目要求. s即为由满足要求的数,在题目中表示有s个椰子,n个人说好第二天将椰子平分,但是午夜的时候,一个人偷偷爬起来,将椰子分成n份,并且剩了m个,就将m个拿给了猴子,并且自己藏起来一份:紧接着第2个人,第3个人都按照相同的方法一直到最后一个人:然后第二天,剩下的椰子刚好平分给这n个人,这回没有猴子的了. 解题思路:这题主要是找到满足的s的个数,a数组表示说第i个