HDU5763 卡特兰数的应用

  附上题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5673, 这个题的大意是在坐标原点有一个机器人, 这个机器人每次可以选择向左走向右走休息一秒, 但是不能走向负半轴, 现在机器人进过一系列运动之后返回了坐标原点, 问你有多少种情况可以使机器人到达坐标原点。

分析:由于机器人开始在坐标原点 最后也在坐标原点, 因此我们可以知道机器人向左走的步数和向右走的步数想同, 且最大是n/2, 因此我们枚举机器人向右走的步数i, 从n中走法中选出2*i个不歇息的点的方案数就是C(n, 2*i), 然后我们就要知道机器人2*i步走的合法的方案数, 仔细思考下我们发现这个方案数和括号合法的个数非常相似, 而括号匹配的个数正好是Cata(i), 因此最终答案就是sigma(C(n, 2*i)*cata(i))  0<=i<=n/2, 代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;
typedef long long LL;
LL M = 1000000007;
const int maxn = 1000000 + 100;
LL nfic[maxn*2], rev_nfic[maxn*2];
LL cata[maxn];

LL qk_mod(LL a, LL b){
    LL res = 1;
    while(b > 0){
        if(b&1)
            res = (res*a)%M;
        a = (a*a)%M;
        b >>= 1;
    }
    return res;
}

LL Com(LL n, LL m){
    LL res = nfic[n];
    res = res*rev_nfic[m]%M;
    res = res*rev_nfic[n-m]%M;
    return res;
}

int main() {
    int T;
    scanf("%d", &T);
    nfic[0] = 1;
    rev_nfic[0] = 1;
    for(int i=1; i<=2*1000000+3; i++){
        nfic[i] = (i*nfic[i-1])%M;
        rev_nfic[i] = qk_mod(nfic[i], M-2);
    }
    for(int i=0; i<=1000000; i++){
        cata[i] = Com(2*i, i)*qk_mod(i+1, M-2)%M;
    }
    while(T--) {
        int n;
        scanf("%d", &n);
        LL res = 0;
        for(int i=0; i<=n/2; i++){
            res = (res + Com(n, 2*i)*cata[i])%M;
        }
        cout<<res<<endl;
    }
    return 0;
}
时间: 2024-08-24 17:03:42

HDU5763 卡特兰数的应用的相关文章

NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)F题 和谐的比赛(递推 ||卡特兰数(转化成01字符串))

Description 今天西工大举办了一场比赛总共有m+n人,但是有m人比较懒没带电脑,另外的n个人带了电脑.不幸的是,今天机房的电脑全坏了只能用带的电脑,一台电脑最多两人公用,确保n>=m.但是大家来的时间不同,随机次序来机房,带电脑的人直接准备比赛而没带电脑的人需要向带电脑并还没和别人公用的人求助(当然会答应).但是,如果不存在带电脑并还没和别人公用的人,那他就要等了,等是很让人头疼的,这就不和谐了,当然假如没有这样的情况发生比赛是很和谐的. Input 输入多组数据,每组数据只有一行m(

hdu 5177 (1e18范围的卡特兰数)

hdu 5177 (1e18范围的卡特兰数) 题意: 求第n个卡特兰数,模3814697265625 (5^18) 限制: 有20组数据,1 <= n <= 1e18 思路: 1. 卡特兰数的表达式: ans = 1/(n+1) * C(2*n,n) -> ans = 1/(n+1) * (2n)! / n! / n!    ---1式 2. 因为要模5^18,求逆元要求互质,所以先把"1式"中的因子5全部去掉 3. 然后看不含因子5的阶乘,f(n!) 4. 设g(x

hdu 4828 Grids(拓展欧几里得+卡特兰数)

题目链接:hdu 4828 Grids 题目大意:略. 解题思路:将上一行看成是入栈,下一行看成是出栈,那么执着的方案就是卡特兰数,用递推的方式求解. #include <cstdio> #include <cstring> typedef long long ll; const int N = 1000005; const ll MOD = 1e9+7; ll dp[N]; ll extendGcd(ll a, ll b, ll& x, ll& y) { if (

uva 1478 - Delta Wave(递推+大数+卡特兰数+组合数学)

题目链接:uva 1478 - Delta Wave 题目大意:对于每个位置来说,可以向上,水平,向下,坐标不能位负,每次上下移动最多为1, 给定n问说有多少种不同的图.结果对10100取模. 解题思路:因为最后都要落回y=0的位置,所以上升的次数和下降的次数是相同的,并且上升下降的关系满足出栈入栈的关系.即卡特兰数. 所以每次枚举i,表示有i个上升,i个下降,用组合数学枚举出位置,然后累加求和. C(2?in)?f(i)=C(2?i?2n)?f(i?1)?(n?2?i+1)?(n?2?i+2)

hunnu11562:The Triangle Division of the Convex Polygon(第n个卡特兰数取模)

Problem description   A convex polygon with n edges can be divided into several triangles by some non-intersect diagonals. We denote d(n) is the number of the different ways to divide the convex polygon. For example,when n is 6,there are 14 different

HDU-4828 卡特兰数+带模除法

题意:给定2行n列的长方形,然后把1—2*n的数字填进方格内,保证每一行,每一列都是递增序列,求有几种放置方法,对1000000007取余: 思路:本来想用组合数找规律,但是找不出来,搜题解是卡特兰数,而且还有一个难点在于N的范围是1000000,卡特兰数早已数千位,虽然有取余: 解决方法就是用在求卡特兰数的时候快速取余+带模除法: 卡特兰数递归公式1:K(n)=K(n-1) * ((4*n-2)/(n+1)); 组合数公式2:K[n] = C[2*n][n] /(n+1); 看公式1,有个除法

特殊函数卡特兰数 hdu 1134

Game of Connections Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3352    Accepted Submission(s): 1910 Problem Description This is a small but ancient game. You are supposed to write down the

HDU2067 卡特兰数

Catalan数: 令h(1)=1,h(0)=1,catalan数满足递归式: h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2) 另类递归式: h(n)=((4*n-2)/(n+1))*h(n-1); 该递推关系的解为: h(n+1)=C(2n,n)/(n+1) (n=1,2,3,...) 递推关系的另类解: h(n) = C(2n, n) - C(2n, n-1) 卡特兰数的应用: •//n个节点的二叉树的所有可能形态数n个

HDU 1133 Buy the Ticket 卡特兰数

设50元的人为+1 100元的人为-1 满足前任意k个人的和大于等于0 卡特兰数 C(n+m, m)-C(n+m, m+1)*n!*m! import java.math.*; import java.util.*; public class Main { /** * @param args */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int cas = 1; while(tru