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

96 篇文章 0 订阅

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


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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值