hdu4928

博客图片

题目链接

hdu4828

题目概述

        有一个(2*N)的格子,现在将(1~2N)(2N)个数放到这些格子中,每个格子放一个数,要求每一行后一个总比前一个大,每一列后面的比前面的大,即(a_{ij} < a_{(i+1)j}, a_{ij} < a_{i(j+1)}).其中测试的组数(T(1 leq T leq 10^5),)数据(N(1 leq N leq 10^6)).

解题思路

        (Catalan)数取模计算的裸题,是<组合数学>这本书课后习题的第二个习题.因为这里模数(M=10^9+7)是一个素数,可以用扩展欧几里得计算出逆元,然后用第二个公式(C_n=frac{4*n-2}{n+1}C_{n-1})打表计算.

代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const int M = 1e9+7;
ll C[N];
// 扩展欧几里得
void extend_gcd(ll a, ll b, ll &x, ll &y){
    if (b == 0){
        x = 1;
        y = 0;
        return;
    }
    extend_gcd(b, a % b, x, y);
    ll temp = x;
    x = y;
    y = temp - (a / b) * y;
}
// 求逆元
ll mod_inverse(ll a, ll m){
    ll x, y;
    extend_gcd(a, m, x,y);
    return (m + x % m)% m;
}

// 打表用递推式计算C_n
void calculate(){
    C[0] = 1;
    for (int i = 1; i < N; i++){
        C[i] = (C[i - 1] * (4 * i - 2)) % M;
        C[i] = (C[i] * mod_inverse(i + 1, M)) % M;
    }
}

int main(int argc, const char** argv) {
    calculate();
    int n = 0;
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; ++i){
        scanf("%d", &n);
        printf("Case #%d:
%lld
", i+1, C[n]);
    }
    return 0;
}

其它

原文地址:https://www.cnblogs.com/2018slgys/p/13303125.html