HDU2067_小兔的棋盘_catalan_递推

题目大意: Problem Description 小兔的叔叔从外面旅游回来给她带来了一个礼物,小兔高兴地跑回自己的房间,拆开一看是一个棋盘,小兔有所失望。不过没过几天发现了棋盘的好玩之处。从起点(0,0)走到终点(n,n)的最短路径数是C(2n,n),现在小兔又想如果不穿越对角线(但可接触对角线上的格点),这样的路径数有多少?小兔想了很长时间都没想出来,现在想请你帮助小兔解决这个问题,对于你来说应该不难吧! 解题思路: 看了一下数据,再加上有点感觉是catalan,发现原来是catalan的2倍,嘿嘿,就用catalan大数求了一下。后来看了题解,才发现原来还可以递推,只是,catalan数达到了35的两倍,恐怕__int64也只能刚刚好容下吧,好吧,有些题还真是得试试才知道。 递推代码:
#include
using namespace std;
const int MAX = 36;
int main(void)
{
    int n, cas_c = 1;
    __int64 f[MAX][MAX];
    memset(f, 0, sizeof(f));
    f[0][0] = 1;

    while(scanf("%d", &n), n >= 0)
    {
        for(int i = 1; i <= n; i++)
        {
            f[i][0] = f[i-1][0];
            for(int j = 1; j < i; j++)
            {
                f[i][j] = f[i][j-1] + f[i-1][j];
            }
            f[i][i] = f[i][i-1];
        }
        printf("%d %d %I64d\n", cas_c++, n, 2 * f[n][n]);
    }
    return 0;
}
代码: catalan大数运算:
//h(n)=h(n-1)*(4*n-2)/(n+1); h(0) = 1;
#include
using namespace std;
const int MAX_LEN = 10005;
const int MAX_NUM = 36;
int catalan[MAX_NUM][MAX_LEN];

void multip(int *cata, int b, int &len)
{
	int carry = 0;
	for(int i = 0; i < len; i++)
	{
		int temp = cata[i] * b + carry;
		cata[i] = temp % 10;
		carry = temp / 10;
	}
	while(carry)
	{
		len++;
		cata[len-1] = carry % 10;
		carry /= 10;
	}
	return ;
}

void division(int *cata, int b, int &len)
{
	int r = 0;
	for(int i = len-1; i >= 0; i--)
	{
		int temp = cata[i] + r * 10;
		cata[i] = temp / b;
		r = temp % b;
	}
	while(!cata[len-1])
	{
		len--;
	}
	return ;
}

int main(void)
{
	int len[MAX_NUM];
	memset(catalan, 0, sizeof(catalan));
	memset(len, 0, sizeof(len));
	catalan[0][0] = 1;
	len[0] = 1;

	for(int i = 1; i < MAX_NUM; i++)
	{
		memcpy(catalan[i], catalan[i-1], sizeof(catalan[i-1]));
		len[i] = len[i-1];
		multip(catalan[i], 4*i-2, len[i]);
		division(catalan[i], i+1, len[i]);
	}
	//for(int i = 0; i < 20; i++)
	//{
	//	for(int j = len[i]-1; j >= 0; j--)
	//	{
	//		printf("%d", catalan[i][j]);
	//	}
	//	printf("\n");
	//}
	int n, cas_c = 1;
	while(scanf("%d", &n), n >= 0)
	{
		multip(catalan[n], 2, len[n]);//卡特兰数的两倍
		printf("%d %d ", cas_c++, n);
		for(int i = len[n]-1; i >= 0; i--)
		{
			printf("%d", catalan[n][i]);
		}
		printf("\n");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/cchun/p/2520229.html