HDU ACM 1134 Game of Connections / 1130 How Many Trees?(卡特兰数)
【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=1134
【解题背景】这题不会做,自己推公式推了一段时间,将n=3和n=4的情况列出来了,只发现第n项与第n-1项有关系,上网搜索的时候发现是组合数学中关于Catalan(卡特兰)数的运用.
以下资料来自网络,整理以备记录学习:
【来源链接】
http://baike.baidu.com/view/2499752.htm
http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/
Catalan序列是一个整数序列,其通项公式是 我们从中取出的Cn就叫做第 n 个 Catalan 数,前17个 Catalan 数分别是:
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670
令h(0) = 1,h(1) = 1,catalan 数满足递推式:
h(n) = h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)
另类递归式:
h(n)=((4*n-2)/(n+1))*h(n-1);
该递推关系的解为:
h(n+1)=C(2n,n)/(n+1) (n=1,2,3,...)
Catalan序列主要有几类运用:
1.括号化问题:
矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n-1)种)
2.出栈次序问题:
一个栈(无穷大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?
类似:有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)
3.将多边行划分为三角形问题:
将一个凸多边形区域分成三角形区域的方法数?
类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?(也就是本题)
4.给顶节点组成二叉树的问题:
给定n个节点,能构成多少种不同的二叉树?
(能构成h(n)个,这个公式的下标是从h(0)=1开始的)
【随笔】:本来知道这个公式之后想打表打出100个Catalan数,将公式化简了一下且用代码尝试了一下:
1 if(n == 1 || n == 2){ 2 printf("1\n"); 3 continue; 4 } 5 int sum = 1; 6 for(int t=2*n-1; t>n+1; t-=2) 7 sum *= t; 8 //func(int m)函数求m的阶乘,func_pow(int a, int b) 函数求a的b次方 9 printf("%d\n", sum*func_pow(2, n/2)/func(n/2+n%2));
后来发现这也是大数处理的问题,翻看之前自己写的大数相乘和大数相除的代码,发现写的很吃力,干脆上网找大数处理的若干代码,发现可以很简单的进行大数相乘及大数相除,即为现在的Ac源代码中的大数处理
源码来自:http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/
1 #include<iostream> 2 #define MAX 100 3 #define BASE 10000 4 5 using namespace std; 6 7 void multiply(int a[],int Max,int b) //大数乘法,注意参数的传递 8 { 9 int i,array=0; 10 for (i = Max-1; i >= 0; i--) 11 { 12 array += b * a[i]; 13 a[i] = array % BASE; // 数组每一位存放大数的四位数字 14 array /= BASE; 15 } 16 return; 17 } 18 19 void divide(int a[], int Max, int b) //模拟大数除法 20 { 21 int i, div = 0; 22 for (i = 0; i < Max; i++) 23 { 24 div = div * BASE + a[i]; 25 a[i] = div / b; 26 div %= b; 27 } 28 } 29 int main() 30 { 31 int a[101][MAX],i, n; 32 memset(a[1],0,MAX*sizeof(int)); 33 for (i=2, a[1][MAX-1] = 1; i < 101; i++) // 高坐标存放大数低位 34 { 35 memcpy(a[i], a[i-1], MAX * sizeof(int)); //h[i] = h[i-1]; 36 multiply(a[i], MAX, 4 * i - 2); //h[i] *= (4*i-2); 37 divide(a[i], MAX, i + 1); //h[i] /= (i+1); 38 } 39 while (cin >> n && n != -1) 40 { 41 for (i = 0; i < MAX && a[n][i] == 0; i++); //去掉数组前为0的数字。 42 cout << a[n][i++]; //输出第一个非0数 43 for (; i < MAX; i++) 44 { 45 printf("%04d",a[n][i]); //输出后面的数,并每位都保持4位长度!(32767) 46 } 47 cout << endl; 48 } 49 return 0; 50 }

更多内容请关注个人微信公众号 物役记 (微信号:materialchains)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?