MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

                 卡特兰数专题

更多卡特兰数资料 请看  卡特兰数
 
HDU 1023 1130  1134  2067 都是标准的卡特兰数, 具体说明请见 卡特兰数  ,只是有一点需要注意, 在35以下的catalan数

可以直接使用 long long 或 __int64 提交的, 但是当 N 超过35 之后, 这就需要大数了.

下面是 2067 的 long long 代码 ,详细请见  (  2067 小兔的棋盘 解题报告 ) 没有使用递归式 , 直接用的catalan 的 迭代式. :

//MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

#include<iostream>
using namespace std;
typedef long long int64;
int64 f[37][37];
int main()
{
    int ca=0;
    int N;
    while ( cin >> N , N + 1 )
    {
        ++ ca;
        for ( int i = 1;i <= N; ++ i )
        {
              f[0][i] = 1;
        }
        for ( int i = 1; i < N; ++ i )
        {
              for ( int j = i; j <= N; ++ j )
              {
                    if ( i == j )
                    {
                         f[i][j] = f[i-1][j];
                    }
                    else
                    {
                         f[i][j] = f[i-1][j] + f[i][j-1];
                    }
              }
        }
        printf("%d %d %I64d\n", ca, N, 2 * f[N-1][N] );
    }
    return 0;
}

除了 2067 外, 其他的题目均是大数的类型, 在这里, 各位 ACMer , 请出你们的大数模板吧 .

或者某些代码牛人可以自己手打 <-------0rz

写好代码后 只需按题目要求格式做相应的改变, 便能直接AC.  1133 稍微有点不同. 会在

最后给出它的解题报告.

1023  1130 1134 直接使用 catalan数 的递归式 ,代码如下, 使用的是高精度乘法  ( 需要在输入结束控制方面根据各题做相应变化 ) :

//MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

#include<iostream>
using namespace std;
#define MAX 105
#define BASE 10000
typedef int myType[MAX+10];
void multiply ( int a[], int Max, int b )  //大数乘小数
{
    int i,array=0;
    for (i=Max-1; i>=0; i--)   
    {
        array+=b*a[i];
        a[i] = array%BASE;
        array /= BASE;   
    }
}
 
void divide ( int a[], int Max, int b )  //大数除小数
{
    int i,div=0;
    for (i=0;i<Max; i++)   
    {
        div = div*BASE + a[i];
        a[i] = div / b;
        div %= b;
    }
}
void outPut ( myType ctl[MAX] ,int N )
{
     int i = 0;
     while ( i < MAX && ctl[N][i] == 0 )
     {
             i ++ ; //去前导0 
     }
     cout << ctl[N][i++];             
     while ( i < MAX )   
     {
             printf ( "%04d", ctl[N][i++] );   
     } 
     cout << endl; 
}
void setNum ( myType ctl[MAX] )
{
     memset ( ctl[1], 0, MAX * sizeof ( int ) );
     ctl[1][MAX-1] = 1;
     for ( int i = 2; i < 101; i ++ )
     {
         memcpy ( ctl[i], ctl[i-1], MAX * sizeof ( int ) );      
         multiply ( ctl[i], MAX, 4 * i - 2 );               
         divide ( ctl[i], MAX, i + 1 );                  
     } 
}
myType ctl[MAX]; 
int main()
{
    setNum ( ctl );
    int N; 
    while ( cin >> N )     // 这里根据各题要求需要做相应变化
    {
           outPut ( ctl, N ); 
    }
    return 0;
}

1133 公式推导如下 :

//MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

( C(m+n, n) - C(m+n, m+1) ) * m! * n! 化简即 (m+n)! * (m-n+1) / (m+1)

推导过程如下 :

m个人拿50,n个人拿100

1:    所以如果 n > m,那么排序方法数为 0 这一点很容易想清楚

2:    现在我们假设 拿50的人用 ‘0’表示, 拿100的人用 1 表示。

如果有这么一个序列 0101101001001111.

当第K个位置出现1的个数多余0的个数时就是一个不合法序列了
 
      假设m=4 n=3的一个序列是:0110100 显然,它不合法, 现在我们把它稍微变化一下:

把第二个1(这个1前面的都是合法的)后面的所有位0变成1,1变成0

就得到 0111011 这个序列1的数量多于0的数量, 显然不合法, 但现在的关键不是看这个序列是不是合法的

关键是:它和我们的不合法序列 0110100 成一一对应的关系

也就是说任意一个不合法序列(m个0,n个1), 都可以由另外一个序列(n-1个0和m+1个1)得到

另外我们知道,一个序列要么是合法的,要么是不合法的

所以,合法序列数量 = 序列总数量 - 不合法序列的总量

序列总数可以这样计算m+n 个位置中, 选择 n 个位置出来填上 1, 所以是 C(m+n, n)

不合法序列的数量就是: m+n 个位置中, 选择 m+1 个位置出来填上 1 所以是 C(m+n, m+1)

然后每个人都是不一样的,所以需要全排列 m! * n! 
      
     所以最后的公式为 :  ( C(m+n, n) - C(m+n, m+1) ) * m! * n! 化简即 (m+n)! * (m-n+1) / (m+1)

推广:
      如果原来有p张50元的话,那么不合法的序列的数量应该是:任意一个不合法序列(m个0,n个1),
 
      都可以由另外一个序列(n-1个0和m+1+p个1)得到,所以是m+n 个位置中, 选择 m+1+p 个位置

出来填上 1 所以是 C(m+n, m+1+p) 接下来的化简就不推了.

代码如下 :

//MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

#include <iostream>
#include <string>
using namespace std;
#define MAX 100
#define BASE 10000
void multiply(int a[],int Max,int b)  //大数乘小数
{
    int i,array=0;
    for (i=Max-1; i>=0; i--)   
    {
        array+=b*a[i];
        a[i] = array%BASE;
        array /= BASE;   
    }
}
 
void divide(int a[], int Max, int b)  //大数除小数
{
    int i,div=0;
    for (i=0;i<Max; i++)   
    {
        div = div*BASE + a[i];
        a[i] = div / b;
        div %= b;
    }
}
int fact[205][MAX];
void setFact ()
{
     fact[0][MAX-1] = fact[1][MAX-1] = 1;
     for ( int i = 2; i <= 200; ++ i )
     {
           memcpy ( fact[i] , fact[i-1] , MAX * sizeof ( int ) );
           multiply ( fact[i] , MAX , i ); 
     } 
}
void outPut ( int ctl[MAX] )
{
     int i = 0;
     while ( i < MAX && ctl[i] == 0 )
     {
             i ++ ; //去前导0 
     }
     printf ( "%d", ctl[i++] );             
     while ( i < MAX )   
     {
             printf ( "%04d", ctl[i++] );   
     } 
     putchar ( '\n' ); 
}
int res[MAX];
int main ()
{
     int M,N;
     int ca = 1;
     setFact();
     while ( cin >> M >> N , M + N )
     {
             printf ( "Test #%d:\n",ca++ );
             if ( N > M )
             {
                  puts ( "0" );
                  continue; 
             }
             memcpy ( res , fact[M+N] , MAX * sizeof ( int ) );      //阶乘 ( m + n )!
             multiply ( res, MAX, M - N + 1 );                               //( m + n )! * ( m-n+1 )
             divide ( res, MAX, M + 1 );                                        //( m + n )! * ( m-n+1 )  / ( m+ 1 )         
             outPut ( res );
     }
     return 0;
}

转载于:https://www.cnblogs.com/MiYu/archive/2010/08/18/1802486.html

HDOJ HDU 1023 1130 1133 1134 2067 ACM 1023 1130 1133 1134 2067 IN HDU ( 卡特兰数 专题 catalan )...相关推荐

  1. 【HDU - 1134 】Game of Connections(JAVA大数加法,卡特兰数)

    题干: This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, ... , 2n - ...

  2. ACM教程 - 卡特兰数(Catalan)算法

    一.什么是Catalan数(Catalan数是许多计数问题的最终形式) Catalan序列是一个整数序列,其通项公式是: 递推公式 1: C(n) = C(1)*C(n-1) + C(2)*C(n-2 ...

  3. ACM常用数列(斐波那契数列、卡特兰数、贝尔数、斯特灵数)

    斐波那契数列:任意一个数是其前两位数只和,即f(i)=f(i-1)+f(i-2),f(1)=f(2)=1 该数列也满足黄金分割比例,所以又成为黄金分割数列 相关题目链接:Fibbonacci Numb ...

  4. 数论二(hdoj 卡特兰数)

    卡特兰数: 1 通项公式:h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!) 2递推公式:h(n)=((4*n-2)/(n+1))*h(n-1); h(n)=h(0)*h(n ...

  5. HDU 5673 Robot 卡特兰数

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5673 题目描述: 一个人从原点开始向右走, 要求N秒后回到原点, 且过程中不能到负半轴, 人有两种操 ...

  6. HDU 3240 Counting Binary Trees 数论-卡特兰数

    题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3240 卡特兰数递推公式h(i)=h(i-1)*(4*i-2)/(i+1) 如果直接算每一步,然后mo ...

  7. HDOJ 2227 HDU 2227 Find the nondecreasing subsequences ACM 2227 IN HDU

    MiYu原创, 转帖请注明 : 转载自 ______________白白の屋   题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=2227 题目描述: ...

  8. HDOJ 1010 HDU 1010 Tempter of the Bone ACM 1010 IN HDU

    MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目描述: 代码 ...

  9. HDOJ 2066 HDU 2066 一个人的旅行 ACM 2066 IN HDU

    MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 题目地址:          http://acm.hdu.edu.cn/showproblem.php?pid=2066 ...

  10. HDOJ/HDU 1133 Buy the Ticket(数论~卡特兰数~大数~)

    Problem Description The "Harry Potter and the Goblet of Fire" will be on show in the next ...

最新文章

  1. Fragment使用小技巧
  2. luncene 查询字符串的解析—QueryParser类
  3. Boost:bind绑定的function<>测试程序
  4. Qt操作SQLite数据库练习(20200215)
  5. Metasploit Framework(MSF)的使用
  6. ycsb 测试验证模式的mongodb
  7. 如何运行vue项目(从gethub上download的开源项目)
  8. python程序员面试自我介绍_如何拿到面试公司一半Offer——我的Python求职之路
  9. VS学习笔记(一)创建C++项目
  10. bzoj1864 [Zjoi2006]三色二叉树
  11. HITRAN数据库的使用及考虑辐射时喷管烧蚀的仿真(附代码)
  12. linux系统的超级管理员,系统的超级管理员:root《 Linux 文件与目录权限 》
  13. 计算机专业中怎么样绘制神经网络结构图
  14. css三实现ui,纯CSS实现常见的UI效果
  15. MyBatis为什么这么“屌”?这些MyBatis的秘密,分分钟吊打面试官
  16. VUE 项目实现大屏展示的响应式
  17. MHA和PXC的区别
  18. 基于Java的网络流量分析软件设计
  19. 台式安装nas系统_从0开始使用“矿渣”低成本打造家庭NAS,黑群晖系统安装(中)...
  20. 去掉clover的广告方法

热门文章

  1. 高并发架构系列:Kafka、RocketMQ、RabbitMQ的优劣势比较
  2. 德国Vue.js2终极开发教程024--32
  3. ES6学习笔记(对象)
  4. ARC077C pushpush 递推
  5. NoClassDefFoundError: javax/xml/bind/JAXBException-springboot
  6. 用JAVA实现小学四则运算
  7. 小程序中canvas绘制网络图片
  8. 《Linux/UNIX 系统编程手册》学习笔记
  9. 1.2 SQL注入原理-手工联合查询
  10. 系统性能优化- Session丢失