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; }