卡特兰数(Catalan)高精度实现

    卡特兰数也算是一个应用广泛的数列,它能够解决一系列问题(括号化,出栈次序,凸多边形三角划分,给定节点组成二叉搜索树问题等),我们以括号化题目为例:

     CODEVS[5112]:

题目描述 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.
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值