卡特兰数的应用都可以归结到一种情况:有两种操作,分别为操作一和操作二,它们的操作次数相同,都为 N,且在进行第 K 次操作二前必须先进行至少 K 次操作一,问有多少中情况?结果就Catalan(N)。
通用卡特兰数打表模板:
//h( n ) = ( ( 4*n-2 )/( n+1 )*h( n-1 ) );
//*******************************
//打表卡特兰数
//第 n个 卡特兰数存在a[n]中,a[n][0]表示长度;
//注意数是倒着存的,个位是 a[n][1] 输出时注意倒过来。
//*********************************
#include<bits/stdc++.h>
using namespace std;
int a[105][250];
void ktl()
{
int i,j,yu,len;
a[1][0]=1;
a[1][1]=1;
len=1;
for(i=2;i<101;i++)
{
yu=0;
for(j=1;j<=len;j++)
{
int t=(a[i-1][j])*(4*i-2)+yu;
//如果是求考虑顺序的排列,如不同点敏感的n节点的二叉树种类则改成这句即可
//int t=(a[i-1][j])*(4*i-2)*i+yu;
yu=t/10;
a[i][j]=t%10;
}
while(yu)
{
a[i][++len]=yu%10;
yu/=10;
}
for(j=len;j>=1;j--)
{
int t=a[i][j]+yu*10;
a[i][j]=t/(i+1);
yu=t%(i+1);
}
while(!a[i][len])
{
len--;
}
a[i][0]=len;
}
}
int main()
{
ktl();
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=a[n][0];i>0;i--)
{
printf("%d",a[n][i]);
}
puts("");
}
return 0;
}
Catalan数的典型应用:
1.由n个+1和n个-1组成的排列中,满足前缀和>=0的排列有Catalan(N)种。
2.括号化问题。左括号和右括号各有n个时,合法的括号表达式的个数有Catalan(N)种。
3.有n+1个数连乘,乘法顺序有Catalan(N)种,相当于在式子上加括号。
4.n个数按照特定顺序入栈,出栈顺序随意,可以形成的排列的种类有Catalan(N)种。
5.给定N个节点,能构成Catalan(N)种种形状不同的二叉树。
6.n个非叶节点的满二叉树的形态数为Catalan(N)。
7.对于一个n*n的正方形网格,每次只能向右或者向上移动一格,那么从左下角到右上角的不同种类有Catalan(N)种。
8.对于在n位的2进制中,有m个0,其余为1的catalan数为:C(n,m)-C(n,m-1)。
9.对凸n+2边形进行不同的三角形分割(只连接顶点对形成n个三角形)数为Catalan(N)。
10.将有2n个元素的集合中的元素两两分为n个子集,若任意两个子集都不交叉,那么我们称此划分为一个不交叉划分。此时不交叉的划分数是Catalan(N)。
11.n层的阶梯切割为n个矩形的切法数也是Catalan(N)。
12.在一个2*n的格子中填入1到2n这些数值使得每个格子内的数值都比其右边和上边的所有数值都小的情况数也是Catalan(N)。
若h(0)=1;h(1)=1;h(2)=2;h(3)=5; ····有另类的递归式
另类递归式:
h(n)=h(n-1)(4n-2)/(n+1);
该递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=1,2,3,…)
原文:https://www.cnblogs.com/LiHior/p/9468916.html
https://www.cnblogs.com/kuangbin/archive/2012/03/21/2410516.html
递推式: h(n)=h(n-1)(4n-2)/(n+1);
1、前三十项卡特兰数表
[1,1,2,5,14,42,132,429,1430,4862,16796,58786,
208012,742900,2674440,9694845,35357670,129644790,
477638700,1767263190,6564120420,24466267020,
91482563640,343059613650,1289904147324,
4861946401452,18367353072152,69533550916004,
263747951750360,1002242216651368,3814986502092304]
2、卡特兰数求模模板
const int C_maxn = 1e4 + 10;
LL CatalanNum[C_maxn];
LL inv[C_maxn];
inline void Catalan_Mod(int N, LL mod)
{
inv[1] = 1;
for(int i=2; i<=N+1; i++)///线性预处理 1 ~ N 关于 mod 的逆元
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
CatalanNum[0] = CatalanNum[1] = 1;
for(int i=2; i<=N; i++)
CatalanNum[i] = CatalanNum[i-1] * (4 * i - 2) %mod * inv[i+1] %mod;
}
3、卡特兰大数模板
#include<bits/stdc++.h>
using namespace std;
const int C_maxn = 100 + 10;///项数
int Catalan_Num[C_maxn][1000];///保存卡特兰大数、第二维为具体每个数位的值
int NumLen[C_maxn];///每个大数的数长度、输出的时候需倒序输出
void catalan() //求卡特兰数
{
int i, j, len, carry, temp;
Catalan_Num[1][0] = NumLen[1] = 1;
len = 1;
for(i = 2; i < 100; i++)
{
for(j = 0; j < len; j++) //乘法
Catalan_Num[i][j] = Catalan_Num[i-1][j]*(4*(i-1)+2);
carry = 0;
for(j = 0; j < len; j++) //处理相乘结果
{
temp = Catalan_Num[i][j] + carry;
Catalan_Num[i][j] = temp % 10;
carry = temp / 10;
}
while(carry) //进位处理
{
Catalan_Num[i][len++] = carry % 10;
carry /= 10;
}
carry = 0;
for(j = len-1; j >= 0; j--) //除法
{
temp = carry*10 + Catalan_Num[i][j];
Catalan_Num[i][j] = temp/(i+1);
carry = temp%(i+1);
}
while(!Catalan_Num[i][len-1]) //高位零处理
len --;
NumLen[i] = len;
}
}
int main(void)
{
catalan();
for(int i=1; i<=30; i++){
for(int j=NumLen[i]-1; j>=0; j--){
printf("%d", Catalan_Num[i][j]);
}puts("");
}
return 0;
}
4.求n<=35以内的卡特兰数
ll h[36];
void init()
{
int i,j;
h[0]=h[1]=1;
for(i=2;i<36;i++)
{
h[i]=0;
for(j=0;j<i;j++)
h[i]=h[i]+h[j]*h[i-j-1];
}
}
printf("%lld\n",h[n]);
5.快速求第n位卡特兰数模板
mod1e9+7版
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define ULL unsigned long long
using namespace std;
long long n;
const long long M=1000000007;
long long inv[1000010];
long long last,now=1;
void init()
{
inv[1]=1;
for(int i=2;i<=n+1;i++)inv[i]=(M-M/i)*inv[M%i]%M;
}
int main()
{
scanf("%lld",&n);
init();
for(int i=2;i<=n;i++)
{
last=now;
now=last*(4*i-2)%M*inv[i+1]%M;
}
printf("%lld\n",last);
return 0;
}
6.Java大数打表卡特兰数模板
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
BigInteger s[]=new BigInteger[105];
s[1]=BigInteger.ONE;
for(int i=2;i<105;i++){
s[i]=s[i-1].multiply(BigInteger.valueOf((4*i-2))).divide(BigInteger.valueOf(i+1));
}
while(cin.hasNext()){
int n=cin.nextInt();
System.out.println(s[n]);
}
}
}