卡特兰数

卡特兰数又称卡塔兰数(Catalan Number),是组合数学中一个经常出现在各种计数问题中的数列。


公式

  1.递归公式1:

    $f(n)=\sum \limits_{i=0}^{n-1}f(i)\times f(n-i-1)$

  2.递归公式2:

    $f(n)=\frac{f(n-1)\times (4\times n-2)}{n+1}$

  3.组合公式1:

    $f(n)=\frac{C_{2n}^n}{n+1}$

  4.组合公式2:

    $f(n)=C_{2n}^n-C_{2n}^{n-1}$


代码实现

  1.$n \leqslant 35$

  大了会爆long long

void Catalan()
{
	long long cat[36];
	cat[0]=cat[1]=1;
	for(int i=2;i<36;i++)
	{
		cat[i]=0;
		for(int j=0;j<i;j++)
			cat[i]=cat[i]+cat[j]*cat[i-j-1];
	}
}

  2.$n>35$求$cat(n)\mod p$,借助$Lucas$定理

  $Lucas$定理$\downarrow$

long long fac[N];
long long qpow(long long x,long long y,long long p)
{
	long long res=1;
	while(y)
	{
		if(y%2)res=(res*x)%p;
		y>>=1;
		x=(x*x)%p;
	}
	return res;
}
long long get_C(long long x,long long y,long long p)
{
	if(x<y)return 0;
	return fac[x]%p*qpow(fac[x-y]*fac[y]%p,p-2,p)%p;
}
long long lucas(long long x,long long y,long long p)
{
	if(!y)return 1;
	return (get_C(x%p,y%p,p)*lucas(x/p,y/p,p))%p;
}

  3.利用高精计算卡特兰大数

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a[100000],c[100000];
int mu[5001];
void mul(int p)
{
	int x=0,j;
	for(j=1;j<=a[0];j++)
	{
		a[j]=a[j]*p+x;
		x=a[j]/10;
		a[j]%=10;
	}
	a[j]=x;
	while(a[j]>9)
	{
		a[j+1]=a[j]/10;
		a[j]%=10;
		j++;
	}
	while(a[j]==0&&j>1)j--;
	a[0]=j;
}
void chu(int b)
{        
    int x=0,s=0,t=0;
    memset(c,0,sizeof(c));
    for(int i=1;i<=a[0];i++)
    {
        x=x*10+a[i];
        if(x/b!=0)s++;
        if(s==0)continue;
        c[++t]=x/b;
        x%=b;
    }
    for(int i=1;i<=t;i++)
    	a[i]=c[i];
    a[0]=t;
}     
int main()
{	
	a[0]=a[1]=1;
	scanf("%d",&n);
	for(int i=n+2;i<=2*n;i++)mul(i);
	reverse(a+1,a+a[0]+1);
	for(int i=2;i<=n;i++)chu(i);
	for(int i=1;i<=a[0];i++)printf("%d",a[i]);
}

做题经验

  看见样例输入3,样例输出5,先想卡特兰数。

posted @ 2019-07-23 14:15  HEOI-动动  阅读(317)  评论(0编辑  收藏  举报