卡特兰数也算是一个应用广泛的数列,它能够解决一系列问题(括号化,出栈次序,凸多边形三角划分,给定节点组成二叉搜索树问题等),我们以括号化题目为例:
题目描述 Description
最近刚刚学完栈,小胖子表示括号匹配太水了,大胖子不屑的说:“你是不知道数据可以出多坑啊!!!”
这句话顿时引起了小胖子的鄙夷。他掐指一算,n个’(’和n个’)’原来也没有多少种完全匹配的方式嘛。
n=1时:( ) —— 一种。
n=2时:( )( )
( ( ) ) —— 两种。
n=3时: ( )( )( )
( )( ( ) )
( ( ) )( )
( ( ) ( ) )
( ( ( ) ) ) ——五种
n=4 ……小胖子表示手指不够了(其实是他懒得算了……)。
大胖子接着鄙夷,你有本事接着算下去?
小胖子不服,但是他实在太懒了,所以他请你帮他解决n个’(’和n个’)’能有多少种组合方式使得括号是匹配的?
输入描述 Input Description
只有一行,包含一个正整数n。
输出描述 Output Description
只有一行,只有一个正整数ans,表示有多少种使其匹配的组合方式。
样例输入 Sample Input
2
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
对于70%的数据 0≤n≤30;
对于100%的数据 0≤n≤500。
1· h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2) [h(0)=1; h(1)=1]
2· h(n)=h(n-1)*(4*n-2)/(n+1)
3· h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
4· h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,...)
第二个公式还是很不错的,但要注意的是--别忘了高精度
我们需要在程序里嵌入一个高精度乘法,与高精度除法,再看一眼式子发现只需要写与单精度乘除就行:
(Pascal代码)
<pre name="code" class="plain">var
h:array[0..500] of ansistring; {存卡特兰数}
n:longint;
i:longint;
function GM(s:ansistring;b:longint):ansistring; {高精乘以单精}
var
i,len:integer;
m:longint;
ee:ansistring;
a:array[1..500] of longint;
begin
GM:='';
fillchar(a,sizeof(a),0);
if b=0 then exit('0');
len:=length(s);
for i:=1 to len do a[i]:=ord(s[len-i+1])-48;
for i:=1 to len do a[i]:=a[i]*b;
for i:=1 to len do
begin
a[i+1]:=a[i+1]+a[i] div 10;
a[i]:=a[i] mod 10;
end;
m:=a[i+1];
while m<>0 do
begin
inc(len);
a[len]:=m mod 10;
m:=m div 10;
end;
for i:=len downto 1 do
begin
str(a[i],ee);
GM:=GM+ee;
end;
end;
function GD(sa:ansistring;b:longint):ansistring;{高精除以单精}
var
ee:ansistring;
d:longint;
a,c:array[1..500] of longint;
i,la,len:longint;
begin
d:=0;
GD:='';
la:=length(sa);
fillchar(a,sizeof(a),0);
for i:=la downto 1 do a[la-i+1]:=ord(sa[i])-48;
len:=la;
for i:=len downto 1 do
begin
d:=d*10+a[i];
c[i]:=d div b;
d:=d mod b;
end;
while (len>=1) and (c[len]=0) do dec(len);
for i:=len downto 1 do
begin
str(c[i],ee);
GD:=GD+ee;
end;
end;
begin
readln(n);
h[0]:='1'; {赋初值}
h[1]:='1';
for i:=2 to n do {套用公式}
begin
h[i]:=GM(h[i-1],(4*i-2));
h[i]:=GD(h[i],i+1);
end;
write(h[n]);
end.