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;
}