卡特兰数——小兔的棋盘 (HDU 2067)

Posted mid2dog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了卡特兰数——小兔的棋盘 (HDU 2067)相关的知识,希望对你有一定的参考价值。

前言

在这里存档以免以后再遇见卡特兰数一概不知。。。。


开工

嗯,懵,很懵。

然后据度娘所说是个卡姿兰数,呃,不好意思,卡特兰数。

看了半天卡特兰数也不知道这是个什么魔鬼东西,看得来的方式更令人头大,干脆直接记住推导公式与相应需要用到的情况好啦,毕竟懒癌晚期了

开工!

https://blog.csdn.net/jokerwyt/article/details/77414853
这里面是需要用到卡特兰数的相应情况

记住开头几项以及实际意义中需要用到的应该就好了,嗯哼

这道题就是卡特兰数的一个简单应用,如下图
顺便放上url

而且套公式也不能随便套。。。因为

有两个公式

一个是

这个刚好是不经过对角线的结果

另一个

这个刚好是经过对角线的结果

于是乎,自然而然地选择了第二个,接下来就是快乐的ac时间咯。

等等,还有个问题,C(n,2n)组合数 如何用算法来表达

题目要求达到了35,而35!估计达到了相当恐怖的数字。。。

果断抛弃直接算,选择用递归来算出组合数

递归的话高中学过的

这个公式应该是高中熟知的哈哈

那么递归结束条件就是m为0的时候或者m与n相等的时候出1

你问我为什么m和n相等也出1? C(n,n)不是等于1么。。

于是乎

long long pet(int m,int n)
if ( m==0 || n==m )return 1;
return	pet(m,n-1)+pet(m-1,n-1); 

然后想到杭电oj总是有多组数据,那样就要重复计算好多次,麻烦,于是改成数组,这样就不用重复算了

long long a[100][100]=0;
long long pet(int m,int n)
if ( m==0 || n==m )return 1;
 if (a[m][n]!=0) return a[m][n]; //这样已经计算过就不会向下递归而是直接返回
return	a[m][n]=pet(m,n-1)+pet(m-1,n-1); 

简单明了,开心顺畅
这个就诠释了为什么答案会比卡特兰数大两倍哈哈

代码
#include<stdio.h>
long long a[40][40]=0;
long long pet(int m,int n)

	if(m==0||n==m)return 1;
	if(a[m][n]!=0)return a[m][n];
	return a[m][n]=pet(m,n-1)+pet(m-1,n-1);

int main()
	int num=0,n;
	while(~scanf("%d",&n)&&n!=-1)
		long long x=pet(n,2*n)/(n+1);
		printf("%d %d %lld\\n",++num,n,x*2);
	
 

然后你就会发现审判器说你这是错误答案,到34的时候变成了负数。

重新上百度
发现度娘居然给你了看起来更简单的递推公式,我真的是&¥……%&……%&

然后来个循环叠加就好了

for(int i = 2 ; i <= 35 ; i++)
	for(int j = 0; j<= i-1; j++)
		h[i]+=h[j]*h[i-j-1];


最后ac代码如下

#include<stdio.h>
int main()

	long long h[40]=1,1;
	for(int i = 2 ; i <= 35 ; i++)
		for(int j = 0; j<= i-1; j++)
			h[i]+=h[j]*h[i-j-1];
	int n,num=1; 
	while(scanf("%d",&n)&&n!=-1)
		
		printf("%d %d %lld\\n",num++,n,h[n]*2);
	
	

以上是关于卡特兰数——小兔的棋盘 (HDU 2067)的主要内容,如果未能解决你的问题,请参考以下文章

hdu2067 小兔的棋盘 DP/数学/卡特兰数

I - 小兔的棋盘 (HDU - 2067)

HDU 2067 小兔的棋盘

HDU2067小兔的棋盘

hdu 2067 小兔的棋盘

hdu2067 小兔的棋盘