既求从点(0,0)只能向上或者向右并且不穿越y=x到达点(a,b)有多少总走法...
有公式: C(a+b,min(a,b))-C(a+b,min(a,b)-1) ///
折纸法证明卡特兰数: http://blog.sina.com.cn/s/blog_6917f47301010cno.html
4 () 4 ( 6 ()
1 2 2HintFor the first case the only regular sequence is ()(). For the second case regular sequences are (()) and ()(). For the third case regular sequences are ()()() and ()(()).
/* *********************************************** Author :CKboss Created Time :2015年03月18日 星期三 20时10分21秒 File Name :HDOJ5184.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> using namespace std; typedef long long int LL; const int maxn=1001000; const LL mod=1000000007LL; int n,len; char str[maxn]; LL inv[maxn]; LL jc[maxn],jcv[maxn]; void init() { inv[1]=1; jc[0]=1; jcv[0]=1; jc[1]=1; jcv[1]=1; for(int i=2;i<maxn;i++) { inv[i]=inv[mod%i]*(mod-mod/i)%mod; jc[i]=(jc[i-1]*i)%mod; jcv[i]=(jcv[i-1]*inv[i])%mod; } } LL COMB(LL n,LL m) { if(m<0||m>n) return 0LL; if(m==0||m==n) return 1LL; LL ret=((jc[n]*jcv[n-m])%mod*jcv[m])%mod; return ret; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); while(scanf("%d",&n)!=EOF) { scanf("%s",str); len=strlen(str); bool flag=true; if(n%2==1) flag=false; int left=0,right=0; for(int i=0;i<len&&flag;i++) { if(str[i]=='(') left++; else if(str[i]==')') right++; if(left>=right) continue; else flag=false; } if(flag==false) { puts("0"); continue; } int a=n/2-left; /// remain left int b=n/2-right; /// remain right if(b>a) swap(a,b); LL ans = (COMB(a+b,b)-COMB(a+b,b-1)+mod)%mod; cout<<ans<<endl; } return 0; }