uva10312 - Expression Bracketing 括号划分


Problem A

Expression Bracketing

Input: standard input

Output: standard output

Time Limit: 1 second

Memory Limit: 32 MB

 

Inthis problem you will have to find in how many waysn letters can be bracketed so that the bracketing is non-binarybracketing. For example4 lettershave11 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 sixbracketing are not binary. Given the number of letters you will have to findthe total number of non-binary bracketing.

 

Input

Theinput file contains several lines of input. Each line contains a single integern (0<n<=26). Input isterminated by end of file.

 

Output

For each line of input produce one line of outputwhich denotes the number of non binary bracketing withn letters.

 

Sample Input

3

4

5

10

 

Sample Output

1

6

31

98187


  把括号划分写成树的形式,问有多少种不是二叉树的。

  是二叉树的情况f[n]=f[1]*f[n-1]+f[2]*f[n-2]...+f[n-1]*f[1],很明显是卡塔兰数。

  卡塔兰数公式:

  h(n)=h(n-1)*(4*n-2)/(n+1)

  h(n)=C(2n,n)/(n+1) (n=0,1,2,...)

  h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,...)

  这里用第二个就行。

  关键在怎么求出N个x的所有划分情况。用一个函数DFS表示这n个x至少要划分成两个区间的划分总数,另一个函数DFS2表示这n个x可以划分成任意区间的划分总数(包括一个)。DFS的时候左边最多选n-1个再进行DFS,右边的进行DFS2。DFS2的时候左边可以选n个,右边为空,相当于还是这个区间。因为在调用DFS2的时候,左边已经划出了一部分,调用DFS2的n是已经被上一层划分出的另一部分,所以这个n可以在这一层不划分,到下一层再划分,不划分的话就相当于上个节点有两个儿子,划分的话说明上个节点的儿子大于2个。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<cmath>
#define INF 0x3f3f3f3f
#define MAXN 30
#define MAXM 20010
#define MAXNODE 4*MAXN
#define MOD 1000000000
#define eps 1e-9
using namespace std;
int N;
long long dp[MAXN],dp2[MAXN];
long long DFS2(int n);
long long DFS(int n){
    if(n==1) return 1;
    long long &ans=dp[n];
    if(~ans) return ans;
    ans=0;
    for(int i=1;i<n;i++) ans+=DFS(i)*DFS2(n-i);
    return ans;
}
long long DFS2(int n){
    if(n<=1) return 1;
    long long &ans=dp2[n];
    if(~ans) return ans;
    ans=0;
    for(int i=1;i<=n;i++) ans+=DFS(i)*DFS2(n-i);
    return ans;
}
long long C(int n,int m){
    double temp=0;
    for(int i=0;i<m;i++) temp+=log10(n-i)-log10(i+1);
    return (long long)(pow(10,temp)+0.5);
}
int main(){
    //freopen("in.txt", "r", stdin);
    memset(dp,-1,sizeof(dp));
    memset(dp2,-1,sizeof(dp2));
    while(scanf("%d",&N)!=EOF){
        printf("%lld\n",DFS(N)-C(2*N-2,N-1)/N);
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值