卡特兰数习题集

可参考:https://blog.csdn.net/wentong_Xu/article/details/81428630

1、HDU1023 Train Problem II

出栈序列方案数:f(n)=h(n)

 1 import java.util.Scanner;
 2 import java.io.BufferedInputStream;
 3 import java.math.BigInteger;
 4 public class Main {
 5     public static void main(String[] args) {
 6         // TODO 自动生成的方法存根
 7     BigInteger[] h=new BigInteger[101];
 8     h[0]=new BigInteger("1");
 9     h[1]=new BigInteger("1");
10     int MAXN=100;
11     for(int i=2;i<=MAXN;++i)
12     {
13         h[i]=h[i-1].multiply(BigInteger.valueOf(4*i-2));
14         h[i]=h[i].divide(BigInteger.valueOf(i+1));
15     }
16     Scanner cin=new Scanner(new BufferedInputStream(System.in));
17     while(cin.hasNext())
18     {
19         int n=cin.nextInt();
20         System.out.println(h[n]);
21     }
22     cin.close();
23     }
24 
25 }
View Code

 

2、洛谷P1722 矩阵 II

n个红算筹和n个黑算筹的摆放,前i个中红算筹的个数大于黑算筹的个数,f(2n)=h(n),模100

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int MAXN=100+5;
 5 const int MOD=100;
 6 ll h[MAXN];
 7 int main()
 8 {
 9     h[0]=1,h[1]=1;
10     /*for(int i=2;i<=MAXN;++i)
11     h[i]=h[i-1]*(4*i-2)%MOD/(i+1);*/
12     //上述递推式在这里行不通 
13     for(int i=2;i<=MAXN;++i)
14     {
15         for(int j=0;j<i;++j)
16         h[i]+=h[j]*h[i-j-1]%MOD;
17         h[i]%=MOD;
18     }
19     int n;cin>>n;
20     cout<<h[n]<<endl;
21 }
View Code

动态规划做法:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int MAXN=100+5;
 5 const int MOD=100;
 6 ll dp[MAXN<<1][MAXN];//dp[i][j]表示前i个中有j个是红色 
 7 int main()
 8 {
 9     int n;cin>>n;
10     n*=2;
11     dp[1][1]=1;//第一个一定是红色
12     for(int i=2;i<=n;++i)
13     {
14         for(int j=(i+1)>>1;j<=i;++j)
15         dp[i][j]=(dp[i-1][j]%MOD+dp[i-1][j-1]%MOD)%MOD;//第i个放黑色或红色
16     } 
17     cout<<dp[n][n>>1];
18 }
View Code
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int MAXN=100+5;
 5 const int MOD=100;
 6 ll dp[MAXN<<1][MAXN<<1];//dp[i][j]表示前i个中红色比黑色多j个 
 7 int main()
 8 {
 9     int n;cin>>n;
10     n*=2;
11     dp[1][1]=1;//第一个一定是红色
12     for(int i=2;i<=n;++i)
13     {
14         for(int j=0;j<=i;++j)
15         {
16             dp[i][j]+=dp[i-1][j-1]%MOD;//第i个放红色
17             dp[i][j]+=dp[i-1][j+1]%MOD;//第i个放黑色
18             dp[i][j]%=MOD; 
19         } 
20     } 
21     cout<<dp[n][0];
22 }
View Code

 

3、洛谷P1976 鸡蛋饼

圆上2n个点,用n条线段将这些点连起来,不能有线段相交。f(2n)=h(n)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int MAXN=3e3;
 5 const int MOD=1e8+7;
 6 ll h[MAXN]={1,1};
 7 int main()
 8 {
 9     int n;cin>>n;
10     for(int i=2;i<=n;++i)
11     for(int j=0;j<i;++j)
12     h[i]=(h[j]*h[i-j-1]%MOD+h[i])%MOD;
13     cout<<h[n]<<endl;
14 }
View Code

 

4、HDU2067 小兔的棋盘

棋盘上从(0,0)到(n,n)且不穿越对角线的路径数。

 1 import java.util.Scanner;
 2 import java.io.BufferedInputStream;
 3 import java.math.BigInteger;
 4 public class Main {
 5     public static void main(String[] args) {
 6         // TODO 自动生成的方法存根
 7     BigInteger[] h=new BigInteger[36];
 8     h[0]=new BigInteger("1");
 9     h[1]=new BigInteger("1");
10     int MAXN=35;
11     for(int i=2;i<=MAXN;++i)
12     {
13         h[i]=h[i-1].multiply(BigInteger.valueOf(4*i-2));
14         h[i]=h[i].divide(BigInteger.valueOf(i+1));
15     }
16     Scanner cin=new Scanner(new BufferedInputStream(System.in));
17     int n=cin.nextInt();
18     int count=0;
19     while(n!=-1)
20     {
21         
22         System.out.print(++count+" "+n+" ");
23         System.out.println(h[n].multiply(new BigInteger("2")));
24         n=cin.nextInt();
25     }
26     cin.close();
27     }
28 
29 }
View Code

动态规划做法:

 1 import java.math.BigInteger;
 2 import java.util.Scanner;
 3 import java.io.BufferedInputStream;
 4 public class Main {
 5     static final int MAXN=40;
 6     static BigInteger dp[][] = new BigInteger[MAXN][MAXN]; //dp[i][j]表示(0,0)到(i,j)的方案数
 7     public static void main(String[] args)
 8     {
 9         Scanner cin=new Scanner(new BufferedInputStream(System.in));
10         for(int i=0;i<MAXN;++i)
11             for(int j=0;j<MAXN;++j)
12                 dp[i][j]=BigInteger.ZERO;
13         for(int i=0;i<MAXN;++i) dp[i][0]=BigInteger.ONE;
14         for(int i=1;i<MAXN;++i)//计算右下角
15         {
16             for(int j=1;j<=i;++j)//不穿越对角线
17             {
18                 if(j==i) dp[i][j]=dp[i][j-1];
19                 else dp[i][j]=dp[i-1][j].add(dp[i][j-1]);
20             }
21         }
22         int n=cin.nextInt();
23         int count=0;
24         while(n!=-1)
25         {
26             System.out.print(++count+" "+n+" ");
27             System.out.println(dp[n][n].multiply(new BigInteger("2")));
28             n=cin.nextInt();
29         }
30         cin.close();
31     }
32 }
View Code

 

5、HDU1133 Buy the Ticket

m个100,n个50,扩展的卡特兰

 

 1 import java.util.Scanner;
 2 import java.math.BigInteger;
 3 import java.io.BufferedInputStream;
 4 
 5 public class Main {
 6     static final int MAXN=200+5;
 7     static BigInteger[] fac = new BigInteger[MAXN];
 8     public static void main(String[] args) {
 9         Scanner cin=new Scanner(new BufferedInputStream(System.in));
10         fac[0]=BigInteger.ONE;
11         for(int i=1;i<MAXN;++i) fac[i]=fac[i-1].multiply(BigInteger.valueOf(i));
12         int m=cin.nextInt();
13         int n=cin.nextInt();
14         int count=1;
15         while(m!=0||n!=0)
16         {
17             BigInteger ans=BigInteger.ONE;
18             BigInteger fz=fac[m+n].multiply(BigInteger.valueOf(m+1-n));
19             BigInteger fm=BigInteger.valueOf(m+1);
20             if(m<n) ans=BigInteger.ZERO;
21             else ans=fz.divide(fm);
22             System.out.println("Test #"+count+":");
23             System.out.println(ans);
24             m=cin.nextInt();
25             n=cin.nextInt();
26             count++;
27         }
28         cin.close();
29     }
30 
31 }
View Code

 

6、洛谷 P3200 [HNOI2009]有趣的数列

2n个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种

用Java大数做后面5组数据MLE了,可能大数太大了,又要用数论,告辞!

 

转载于:https://www.cnblogs.com/wangzhebufangqi/p/11250198.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值