百度百科:https://baike.baidu.com/item/%E5%8D%A1%E7%89%B9%E5%85%B0%E6%95%B0/6125746?fr=aladdin
不错的网易博客:http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。
令h(1)=1,h(0)=1,catalan数满足递归式:
h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2)
另类递归式:
h(n)=((4*n-2)/(n+1))*h(n-1);
该递推关系的解为:
h(n+1)=C(2n,n)/(n+1) (n=1,2,3,...)
其前几项为 : 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, ...百科上有的写的很深,不好理解,随着看的博文多了,理解的会深一些 。
自己推的代码如下,当时并不知道这是卡特兰数,比赛时用了一个小时左右硬生生的推出来的:
#include
int main()
{
int n;
long long sum;
long long dp[3005];
dp[0]=1; dp[1]=1; dp[2]=2; dp[3]=5;
for(int i=4;i<=3000;i++)
{
int tem=i;
int cnt=tem/2;
sum=0;
for(int j=0;j
再看看比较官方的代码:
#include
#define mod 100000007
int main()
{
int n;
long long sum;
long long dp[3005];
dp[0]=1; dp[1]=1;
for(int i=2;i<=3002;i++)
{
dp[i]=0;
for(int j=0;j
官方代码Java大数版,在不要求取余的情况下用。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int n;
Scanner cin = new Scanner(System.in);
BigInteger[] bb = new BigInteger[105];
bb[0] = BigInteger.valueOf(1);
bb[1] = BigInteger.valueOf(1);
for (int i = 2; i <= 100; i++) {
bb[i] = BigInteger.valueOf(0);
for (int j = 0; j < i; j++)
bb[i] = bb[i].add(bb[j].multiply(bb[i - j - 1]));
}
while (cin.hasNext()) {
n = cin.nextInt();
if (n == -1)
break;
System.out.println(bb[n]);
}
}
}
h(n)=((4*n-2)/(n+1))*h(n-1); 在计算时就算是double 类型精度也不够,只能算前30个数,所以我用了java高精度,这里以hdu 2067为例。
代码如下:
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
BigDecimal [] BB = new BigDecimal [40];
int inde=0;
BB[0]=BigDecimal.valueOf(1);
BB[1]=BigDecimal.valueOf(1);
for(int i=2;i<=36;i++)
{
BB[i]=BigDecimal.valueOf(4*i-2).multiply(BB[i-1]);
BB[i]=BB[i].divide(BigDecimal.valueOf(i+1));
}
int n;
while(cin.hasNext())
{
n=cin.nextInt();
if(n==-1)
break;
System.out.printf("%d %d ",++inde,n);
System.out.println(BB[n].multiply(BigDecimal.valueOf(2)));
}
cin.close();
}
}
对于n对括号,合法的排列共有C(n,2n) - C(n+1,2n)种.
分析:n对括号,n个左括号,n个右括号;这里可以假设有2n个空,随机选出n空,填入左括号,剩下的由右括号填充。
以两对括号为例 :
先把红色的放上。剩下的是填充的,这样前一半的递推式就解决了。
然后,分析这里面应该剔除的 C(n+1,2n) 种,这里这个方法十分的巧妙;首先假设左括号为1,右括号为-1,从左到右依次加起来,如果这个这个序列不合格的,必然存在一个k使得1~k的和为-1;将1~k这k个括号反转(转化一下,求解),则这n对括号会分为n+1个左括号,n-1个有括号;
综上所述,这样的序列一共C(n+1,2n)种,都是不合法的。
所以C(n,2n) - C(n+1,2n),得证。