zoukankan      html  css  js  c++  java
  • 卡特兰数 Catalan 笔记

    一.公式

    卡特兰数一般公式

      令h(0)=1,h(1)=1,catalan数满足递推式。h(n) = h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)。也就是说,如果能把公式化成上面这种形式的数,就是卡特兰数

    组合公式

      Cn = C(2n,n) / (n+1)

      (化简前 h(n) = c(2n,n)-c(2n,n+1) (n=0,1,2,...) 证明)

    递归公式1

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

    递归公式2

      h(n) = ∑(i=0 to n-1) h(i)*h(n-i-1)

    二.资料

      catalan---卡特兰数(小结)

    三.某些题

    1.在圆上选择2n个等间隔的点。证明将这些点成对连接起来使得所得到的n条线段不相交的方法数等于第n个Catalan数

    设方法数为gn,分别将这些点用1,2,…,2n标记。取定点1,任选另一个偶数点2k,连接点1与点2k。该线段将圆分成K1和K2两部分。对K1,有k-1对点,故有gk-1种方法;对K2,有n-k对点,故有gn-k种方法。所以
       g0=1
       令hn=gn-1,则
       hn+1=h1hn+h2hn-1+…+hnh1  h1=1

       所以gn=g0 gn-1 + g1 gn-1 +...+ gn-1 g0

       即 gn=Cn

    2.二叉树计数:一个有n个结点的二叉树总共有多少种形态

     1 //设当前根节点为k,方案数为h[k],左子树有k-1个节点,右子树有n-k个节点 
     2 //则 h[k]=h[k-1]*h[n-k](k=1 to n) 
     3 //Ans= h[0]h[n-1] + h[1]h[n-2] +...+ h[n-1][0]
     4 //即卡特兰数 
     5 #include<cstdio>
     6 #include<cctype>
     7 using namespace std;
     8 const int N=22;
     9 
    10 int n;
    11 long long H[N];
    12 
    13 int read()
    14 {
    15     int now=0;bool f=0;char c=getchar();
    16     for(;!isdigit(c);c=getchar())
    17       if(c=='-') f=1;
    18     for(;isdigit(c);c=getchar())
    19       now=(now<<3)+(now<<1)+c-'0';
    20     return f?-now:now;
    21 }
    22 
    23 int main()
    24 {
    25     n=read();
    26     H[0]=1;
    27     for(int i=1;i<=n;++i)
    28       H[i]=H[i-1]*(4*i-2)/(i+1);
    29     printf("%lld",H[n]);
    30     return 0;
    31 }
    View Code

    3.出栈次序:一个栈(无穷大)的进栈次序为1、2、3……n。不同的出栈次序有几种。

      我们可以这样想,假设k是最后一个出栈的数。比k早进栈且早出栈的有k-1个数,一共有h(k-1)种方案。比k晚进栈且早出栈的有n-k个数,一共有h(n-k)种方案。所以一共有h(k-1)*h(n-k)种方案。显而易见,k取不同值时,产生的出栈序列是相互独立的,所以结果可以累加。k的取值范围为1至n,所以结果就为h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0)。(转自Blog)
     1 //设k为最后一个出栈的数,
     2 //有k-1个比k早进栈且比k早出栈,有C[k-1]种方案 
     3 //有n-k个比k晚进栈但比k早出栈,有C[n-k]种方案 
     4 //根据乘法原理,C[k]=C[k-1]*C[n-k](k=1 to n) 
     5 //Ans = C[0]C[n-1] + C[1][n-2] +...+ C[n-1][0]
     6 #include<cstdio>
     7 using namespace std;
     8 const int N=22;
     9 
    10 int n;
    11 long long Ca[N];
    12 
    13 int main()
    14 {
    15     scanf("%d",&n);
    16     Ca[0]=1;
    17     for(int i=1;i<=n;++i)
    18       Ca[i]=Ca[i-1]*(4*i-2)/(i+1);
    19     printf("%lld",Ca[n]);
    20     return 0;
    21 }
    View Code

    注:

      long long最大只能到33

    Code:

    1 Ca[0]=1;
    2 for(int i=1;i<=n;++i)
    3     Ca[i]=Ca[i-1]*(4*i-2)/(i+1);
    Catalan

     高精:

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 using namespace std;
     5 const int p=4,mod=10000;
     6 
     7 int C[50005];
     8 
     9 inline int read()
    10 {
    11     int now=0;bool f=0;char c=getchar();
    12     for(;!isdigit(c);c=getchar())
    13       if(c=='-') f=1;
    14     for(;isdigit(c);c=getchar())
    15       now=(now<<3)+(now<<1)+c-'0';
    16     return f?-now:now;
    17 }
    18 
    19 void Print(int n[])
    20 {
    21     printf("%d",n[n[0]]);
    22     for(int i=n[0]-1;i;--i)
    23       printf("%0*d",p,n[i]);
    24     puts("");
    25 }
    26 void Mult(int n[],int t)
    27 {
    28     int x=0;
    29     ++n[0];
    30     for(int i=1;i<=n[0];++i)
    31     {
    32         n[i]=n[i]*t+x;
    33 //        printf("%d:%d
    ",i,n[i]);
    34         x=n[i]/mod;
    35         n[i]%=mod;
    36     }
    37     while(!n[n[0]] && n[0]>1) --n[0];
    38 //    Print(n);
    39 }
    40 void Div(int n[],int t)
    41 {
    42     int x=0;
    43     for(int i=n[0];i;--i)
    44     {
    45         n[i]=x*mod+n[i];
    46         x=n[i]%t;
    47         n[i]/=t;
    48     }
    49     while(!n[n[0]] && n[0]>1) --n[0];
    50 //    Print(n);
    51 }
    52 
    53 int main()
    54 {
    55     int n=read();
    56     C[0]=1;
    57     C[1]=1;
    58     for(int i=1;i<=n;++i)
    59     {
    60 //        C[now]=C[now-1]*(4*i-2)/(i+1);
    61 //        printf("
    %d:
    ",i);
    62         Mult(C,4*i-2);
    63         Div(C,i+1);
    64 //        Print(C);
    65     }
    66     Print(C);
    67     return 0;
    68 }
    CODEVS.3113.二叉树计数2
  • 相关阅读:
    Python中pymssql 的使用操作
    Python连接mysql数据库及简单增删改查操作示例代码
    Python之模块和包的创建与使用
    SQL SERVER将多行数据合并成一行
    SQL Server根据子查询更新语句update
    在VMware虚拟机中安装windows server2016步骤详解(带图解)
    http请求错误合集
    第三方图标库(三)iconMoon
    第三方图标库学习(二)Font Awesome
    MapperScannerConfigurer的原理
  • 原文地址:https://www.cnblogs.com/SovietPower/p/7202443.html
Copyright © 2011-2022 走看看