您的位置:首页 > 其它

Uva 10312 - Expression Bracketing 解题报告(卡特兰数+递推)

2014-04-02 18:02 459 查看
Problem A
Expression Bracketing
Input: standard input
Output: standard output
Time Limit: 1 second
Memory Limit: 32 MB
 

In this problem you will have to find in how many ways n letters can be bracketed so that the bracketing is non-binary bracketing. For example 4 letters have 11 possible bracketing:

 

xxxx, (xx)xx, x(xx)x, xx(xx), (xxx)x, x(xxx), ((xx)x)x, (x(xx))x, (xx)(xx), x((xx)x), x(x(xx)). Of these the first six bracketing are not binary. Given the number of letters you will have to find the total
number of non-binary bracketing.

 

Input

The input file contains several lines of input. Each line contains a single integer n (0<n<=26). Input is terminated by end of file.

 

Output

For each line of input produce one line of output which denotes the number of non binary bracketing with nletters.

 

Sample Input

3

4

5

10

 

Sample Output

1

6

31

98187

[align=center]    [/align]
[align=center]    解题报告: 题目的意思有点难理解。其实是题意没有表达完整。如果p和q是要求的串,那么(pq)也是要求的串。按照这个递归定义即可。[/align]
[align=center]    说白了,这样的串可以形成一颗二叉树。下图所示的串表示(xx)x。[/align]



[align=center]    那么我们可以得出,binary bracketing的数量就是卡特兰数。[/align]
[align=center]    那么其他的呢,non-binary bracketing可以根据总数减去卡特兰数来求得。[/align]
[align=center]    我们分析一下,binary bracketing数构成的是二叉树,bracketing构成的则是所有节点儿子数大于等于2的树的数量。[/align]
[align=center]    据此,我们可以递推了。儿子数大于等于2我们可以这样处理:首先至少分成两部分,我们将第一个儿子分配至多n-1个节点,剩下的继续分配。这样形成的子树数量至少是2。递推下去,最终结果减去卡特兰数即可。[/align]
[align=center]    代码如下:[/align]
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;
LL da[30];
LL db[30];

LL dfs(int n);

LL dfs2(int n)
{
if(n<=1) return 1;

LL &ans = db
;
if(~ans) return ans;

ans=0;
for(int i=1;i<=n;i++)
ans+=dfs(i)*dfs2(n-i);

return ans;
}

LL dfs(int n)
{
if(n==1) return 1;

LL &ans = da
;
if(~ans) return ans;

ans=0;
for(int i=1;i<n;i++)
ans+=dfs(i)*dfs2(n-i);
return ans;
}

LL C(int n, int m)
{
double tmp=0;
for(int i=0;i<m;i++)
tmp+=log10(n-i)-log10(i+1);
return (LL)(pow(10, tmp)+0.5);
}

int main()
{
memset(da, -1, sizeof(da));
memset(db, -1, sizeof(db));

LL n;
while(~scanf("%lld", &n))
{
if(n==1) puts("0");
else printf("%lld\n", dfs(n)-C(2*n-2, n-1)/n);
}
}
    C(2*n-2, n-1)/n是用来求卡特兰数的。数据量不会超过long long。是道不错的题。
[align=center]
[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息