HDU4828 Grids 2014百度之星初赛题解

看看Catalan数的公式:为 Catalan(n) = C(2n, n) / n+1 = C(2n, n) - C(2n, n-1); (公式0)

然后利用全排序表达:Catalan(n) = (2n)! / (n+1) * (n)!*n!;

那么Catalan(n-1) = (2(n-1))! / n * (n-1)!(n-1)!;

然后两者相除就得到:Catalan(n) = (4*n-2) / (n+1) (公式1)//这个就是递归的终极公式了。

一般使用动态规划的递推公式是:Catalan(n) = Catalan(0) * Catalan(n-1) + Catalan(1) * Catalan(n-2) + ... + Catalan(n-1) * Catalan(0);(公式2)

公式1自然比公式2快上一个档次了。以前只会用公式2,使用动态规划或者公式0去做,速度自然慢了。

这就这道题目的要诀了。惭愧啊,当时居然没做出来,因为当时数学水平没跟上。经过一个多月的学习数学,参考了一下网上的程序,终于开窍了。

不过安慰下自己,就是当时做出来的人好像才200人多一点,而且资格赛四道题也不过200人多点做出来的,恰好我做完了。

算法高手到底有多少呢?不少,也不多。-- 废话。

呵呵,给大家一个衡量的大概尺度,可以把这道题做出来的人应该可以说是高手了,起码数学这块过关了。

记得一个好像是什么外国语学院的,居然几分钟做出来了,还是外国语学院的,难倒是英语高手+算法高手,厉害。

当然我也是英语高手,呵呵。


扯远了,最后是所谓乘法逆元问题,可以套模板程序了,要知道推导可以参考组合数学书。

就是GCD扩展的算法。扩展之后的系数就是乘法逆元了。


#include <stdio.h>

const int N = 1000001;
const long long MOD = (long long)1E9 + 7LL;
long long g;

void extGCD(long long a,long long b,long long &x,long long &y)
{
	if(b == 0)
	{
		x = 1, y = 0; 
		g = a;
		return ;
	}
	extGCD(b, a % b, y, x);
	y -= a / b * x;
}

long long modReverse(long long a, long long n)
{
	long long x, y;
	extGCD(a, n, x, y);
	return (x + n) % n;
}

long long Catalan[N];	//0 1 2 3 4  5  6   7   8    9    10    11    12
void genCatalan()	//1 1 2 5 14 42 132 429 1430 4862 16796 58786 208012
{
	Catalan[0] = Catalan[1] = 1LL;
	for (int i = 2; i < N; i++)
	{
		long long tmp = modReverse(i+1LL, MOD);
		Catalan[i] = Catalan[i - 1] * ((i<<2) - 2) % MOD * tmp % MOD;
	}
}

int main() 
{
	genCatalan();
	int T, num;
	scanf("%d", &T);
	for (int t = 1; t <= T; t++)
	{
		scanf("%d", &num);
		printf("Case #%d:\n%I64d\n", t, Catalan[num]);
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值