Brackets---卡特兰数

来源:互联网 发布:喀秋莎软件添加片头 编辑:程序博客网 时间:2024/04/30 05:33

Brackets

题目描述
This year MK is 5 years old. So he decides to learn some arithmetic. But he was confused by how to write the brackets. He has already known that the brackets should match when writing them correctly. Such as “()(())” is correct but “())(” is not.
The problem is that, if there are N pairs of brackets, how many ways that MK can write them correctly?  


输入格式
 There are several test cases. Each case contains a number N (1 <= N <= 1000) indicating the pairs of brackets.
输出
For each case, please output the answer mod 1,000,000,007.
样例输入
5
7
样例输出
42
429

分析:提交了n次,错了n次,超时了n+1次。

主要用到了卡特兰数。公式

为:h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) 

用for来循环,

例如:h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5

所以可用:

for(i=1; i<=1000;i++) 
{     
        for(j=0;j<i;j++) 
{
            a[i]+=a[j]*a[i-j-1]%M;
           a[i]%=M;
        }
}

来求a[i];

关于卡特兰数还有另类递推式:
h(n)=h(n-1)*(4*n-2)/(n+1);

一开始我用的是这个,但是,可能会除不尽。

再者,看到了答案后,觉得可用构造一个函数,来表示啊a[i];

但是超时,很纠结,所以,还是借鉴了一下答案,先表示出来a[10001],然后在从这个数组中直接输出就行,就行了!就是不知道第一次运行时间是不是超时,但是,以后,每次输入,都不会再执行for语句,时间就很少,而且调用函数很费时间,每次输入都要调用,时间会很久。卡特兰数的求法就是for(i=1; i<=1000;i++) 
{     
        for(j=0;j<i;j++) 
{
            a[i]+=a[j]*a[i-j-1]%M;
           a[i]%=M;
        }
};

卡特兰数的应用:

括号化:
矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n-1)种)

出栈次序
一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列

类似问题 买票找零
有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈

凸多边形三角划分
在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。现在的任务是键盘上输入凸多边形的边数n,求不同划分的方案数f(n)

类似问题
一位大城市的律师在她住所以北n个街区和以东n个街区处工作。每天她走2n个街区去上班。如果她从不穿越(但可以碰到)从家到办公室的对角线,那么有多少条可能的道路?
在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?

给定节点组成二叉树
给定N个节点,能构成多少种不同的二叉树?
(能构成h(N)个)

详见网址:http://baike.baidu.com/view/2499752.htm#refIndex_3_2499752

代码如下:

#include<stdio.h>

const int M=1000000007;
int n;
long long a[1001];
int main()
{
int i,j;


a[0]=1;
for(i=1; i<=1000;i++) 
{     
        for(j=0;j<i;j++) 
{
            a[i]+=a[j]*a[i-j-1]%M;
           a[i]%=M;
        }
}
while(scanf("%d",&n)!=EOF)
      printf("%lld\n",a[n]);
return 0;
}
原创粉丝点击