zoukankan      html  css  js  c++  java
  • 浅谈求卡特兰数的几种方法

      卡特兰数是一个很常见的数列,以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为 : 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, ...(摘自百度百科)

    卡特兰数的求解方法

    1.最基本的n^2递推

     例题:https://www.luogu.org/problemnew/show/P1044

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n;
     5 int f[20];
     6 int main()
     7 {
     8     scanf("%d",&n);
     9     f[0]=1;
    10     f[1]=1,f[2]=2;
    11     for(int i=3;i<=n;++i)
    12         for(int j=0;j<i;++j)
    13         f[i]+=f[j]*f[i-j-1];
    14     cout<<f[n]<<endl;
    15     return 0;
    16 } 
    View Code

    此题由于数据范围非常小,既不会t也不会炸int,所以直接n^2求即可。证明不会qwq。

    2.卡特兰数的第n项h(n)=C(2n,n)-C(2n,n-1),所以用求组合数的方法求卡特兰数即可,针对对一个大质数取模的代码

     1 #include<iostream>
     2 #include<cstdio> 
     3 using namespace std;
     4 int n,p;
     5 int js[100005];
     6 int prime[100005];
     7 bool vis[100005];
     8 int cnt[100005];
     9 int qpow(int a,int b)//快速幂求逆元 
    10 {
    11     int ans=1;
    12     while(b)
    13     {
    14         if(b&1)ans=(1ll*a*ans)%p;
    15         a=(1ll*a*a)%p;
    16         b>>=1;
    17     }
    18     return ans;
    19 }
    20 int main()
    21 {
    22     scanf("%d%d",&n,&p);//求第n项,对p取模的结果,p为大质数
    23     js[0]=1;
    24     for(int i=1;i<=2*n;++i)
    25         js[i]=(1ll*js[i-1]*i)%p;
    26     int a=qpow(1ll*js[n]*js[n]%p,p-2),b=qpow(1ll*js[n-1]*js[n+1]%p,p-2);
    27     a=1ll*a*js[2*n]%p,b=1ll*b*js[2*n]%p;
    28     int ans=(a-b+p)%p;//a=C(2n,n)%p,b=C(2n,n-1)%p 
    29     printf("%d",ans);
    30     return 0;
    31 }
    View Code

    3.我们可以由第一种求法看出来卡特兰数增长的是很快的,所以当要求的项数比较大而且不能取模时,需要用到高精,这时分解质因数求卡特兰数就是一个很好的方法。

      例题:https://www.luogu.org/problemnew/show/P2532

    这题蒟蒻做的时候看到样例输入3,输出5,直接想到卡特兰数,没想到是对的,233333333

    代码

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n; 
     5 int prime[1500],cnt;
     6 bool vis[1550];
     7 int tong[1050];
     8 int ans[1100],len;
     9 void cheng(int x,int sum)//高精乘低精
    10 {
    11     while(sum--)
    12     {
    13         for(int i=1;i<=len;++i)ans[i]*=x;
    14         for(int i=1;i<=len;++i)
    15         {
    16             if(ans[i]>9)
    17             {
    18                 ans[i+1]+=ans[i]/10,ans[i]%=10;
    19                 if(i+1>len)len++;
    20             }
    21         }
    22     }
    23 }
    24 int main()
    25 {
    26     scanf("%d",&n);
    27     vis[0]=vis[1]=1;
    28     for(int i=2;i<=2*n;++i)//分解质因数
    29     {
    30         if(!vis[i])prime[++cnt]=i;
    31         for(int j=1;j<=cnt&&prime[j]*i<=2*n;++j)
    32         {
    33             vis[i*prime[j]]=1;
    34             if(i%prime[j]==0)break;
    35         }
    36     }
    37     for(int i=1;i<=cnt;++i)
    38     {
    39         int tmp=2*n;
    40         while(tmp/prime[i]>0)tong[i]+=tmp/prime[i],tmp/=prime[i];
    41         tmp=n;while(tmp/prime[i]>0)tong[i]-=tmp/prime[i],tmp/=prime[i];
    42         tmp=n+1;while(tmp/prime[i]>0)tong[i]-=tmp/prime[i],tmp/=prime[i]; 
    43     }
    44     ans[1]=1,len=1;
    45     for(int i=1;i<=cnt;++i)
    46     {
    47         if(tong[i])
    48         {
    49             cheng(prime[i],tong[i]);
    50         }
    51     }
    52     for(int i=len;i>=1;i--)printf("%d",ans[i]);
    53     return 0;
    54 }
    View Code

    4.卡特兰数的递推公式h(n)=h(n-1)*(4*n-2)/(n+1),不过蒟蒻因为不是很懂,总是觉得没谱,所以从来没有用过这个递推式。

    知世故而不世故,处江湖而远江湖,才是最成熟的善良
  • 相关阅读:
    【Silverlight】Bing Maps系列文章汇总
    《MEF程序设计指南》博文汇总
    Flash中各种图形的绘制
    Bing Maps开发扩展二:基于Oracle Spatial的空间数据分析
    Bing Maps开发扩展三:Bing Maps中渲染ESRI SHP空间数据
    Spring Cloud Gateway
    Spring Cloud Gateway 整合 nacos
    Spring Cloud Gateway 断言(Predicate) (hoxton 版本)
    Python和Node.js支持尾递归吗?
    用OpenCv来做人脸识别
  • 原文地址:https://www.cnblogs.com/yuelian/p/8719175.html
Copyright © 2011-2022 走看看