先推荐一个关于卡特兰数的博客:http://blog.csdn.net/hackbuteer1/article/details/7450250。
卡特兰数一个应用就是,卡特兰数的第n项表示,现在进栈和出栈的次数都是n次,问最后栈空的合法序列的个数。其他例子见上面这个博客。
那么关于这个题目,我们先选出i次右移的(相当于进栈)次数,i次左移的(相当于出栈)次数,那么当前对答案做出的贡献就是C(n,2*i)*cat[i],枚举所有的i计算出答案即可。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 typedef long long ll; 6 const int N = 1000000 + 5; 7 const int mod = (int)1e9 + 7; 8 9 int inv[N],cat[N],C[N]; 10 11 void init() 12 { 13 inv[1] = 1; 14 for(int i=2;i<N;i++) inv[i] = (mod-mod/i) * 1LL * inv[mod % i] % mod; 15 16 cat[0] = cat[1] = 1; 17 for(int i=2;i<=N/2;i++) cat[i] = 1LL* cat[i-1] * (4*i-2) % mod * inv[i+1] % mod; 18 } 19 20 int main() 21 { 22 init(); 23 int T;scanf("%d",&T); 24 while(T--) 25 { 26 int n; 27 scanf("%d",&n); 28 int ans = 0; 29 C[0] = 1; // C(n,0) = 1; 30 for(int i=1;i<=n;i++) C[i] = (ll)C[i-1] * (n-(i-1)) % mod * inv[i] % mod; // O(n)递推组合数C(n,i) 31 for(int i=0;i<=n/2;i++) ans = ((ans + (ll)C[i*2] * cat[i] % mod) % mod + mod) % mod; 32 printf("%d ",ans); 33 } 34 return 0; 35 }