卡特兰数 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\n",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("\n%d:\n",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

 

转载于:https://www.cnblogs.com/SovietPower/p/7202443.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值