acdream 1040: whxnwjq got the champion 卡特兰数

题目大意:

  给出递推公式,求   % 1e9+7

   

    

 

看大神们的思路:除1外,奇数全为0,对于偶数2k,答案为(-1)^k*fact[2k]*catalan(k+1)。p[i]表示i的阶乘。

表示弱菜依旧无法理解哪里看出来的规律,哪怕是 catalan(n) 为 阶乘倍数的关系知道我也没弄出来...求大神普渡~~~

 

AC代码:

View Code
#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<algorithm>

using namespace std;

typedef long long LL;

const int N = 1e7+7;

const int mod = 1e9+7;



LL fact[N];

int n;

LL mult( LL a, LL b)

{

    LL res = 0;

    while( b ){

        if(b&1) if( (res+=a) >= mod ) res -= mod;

        a <<= 1; if( a >= mod ) a -= mod;

        b >>= 1;

    }

    return res;

}



LL ExGcd( LL a, LL b, LL &x, LL &y)

{

    if( b == 0 ){    x = 1; y = 0; return a; }

    LL r = ExGcd( b, a%b, x, y );

    LL t = x;

    x = y; y = t - (a/b)*y;

    return r;

}

LL inverse( LL A ){ //求逆元,简化计算

    LL a = A, b = mod, x, y;

    ExGcd( a, b, x, y );

    return (x%mod+mod)%mod;

}

LL catalan( int x ){

    LL A = inverse( fact[x] ) , B = inverse(x+1); // H(n) = (2n!)*A*A*B

    return mult( mult( fact[x<<1], B ) , mult( A, A)  );

}

void init(){

    fact[0] = 1;

    for(LL i = 1; i <= N; i++)

        fact[i] = fact[i-1]*i%mod;

}

int main(){

    init();    

    while( scanf("%d", &n) != EOF)

    {

        if( n == 1 ) puts("1");

        else if( n&1 ) puts("0");

        else{    

            n /= 2;

            LL ans = 1;

            if( n%2 == 1 ) ans = mod-1;

            //LL ans = mult( fact[n], catalan( n/2 + 1 ) );    

            printf("%lld\n", mult(ans, mult(fact[2*n],catalan(n-1) ) ) );    

        }

    }

    return 0;

}

 

你可能感兴趣的:(Go)