标签:
这题说的给了一个整数n 和一串的括号, 那么要我们计算 最后有n/2对括号的 方案数有多少。
我们可以先预先判断一些不可能组成正确括号对的情况,
然后我们可以将这个问题转化到二维平面上, 令 m = n/2 ,L 为左括号的个数 R为右括号的个数 可以知道还有 m - L 个左括号没用, 有m-R个右括号没用,令他们分别我p=m-R,q=m-L, 然后机的就是 (0,0)点到 (p,q)点 不跨过x=y这条线的方案数,那么我们可以这样做,将 (0,0) 向下移动 1 个单位,(0,-1)-》》》》》(p,q-1) , 假设如果非法那么必须会经过(d,d)这个点,我们知道从(0,-1)到(d,d)和(-1,0)到(d,d)的方案数是一样的,那么我们就知道了从(0,1) 出发的非法的方案数为 (-1,0) 到(p.q-1) 的方案数,那么最终的答案就是 C(p+q,q)-C(p+q,q-1);
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <string.h> 5 #include <vector> 6 using namespace std; 7 const int maxn = 1000000+10; 8 typedef long long LL; 9 const LL mod = 1000000007; 10 LL dp[maxn]; 11 LL mdp[maxn]; 12 LL vdp[maxn]; 13 char str[maxn]; 14 void gcd(LL a, LL b, LL &d, LL &x, LL &y){ 15 if(!b) {d=a; x= 1; y =0;} 16 else{gcd(b,a%b,d,y,x); y -= x*(a/b);} 17 } 18 LL inv(LL a, LL n){ 19 LL d,x,y; 20 gcd(a,n,d,x,y); 21 return d==1 ? (x+n)%n:-1; 22 } 23 int main() 24 { 25 dp[0]=1; 26 for(LL i=1; i<=1000000; ++i){ 27 dp[i]=(dp[i-1]* i)%mod; 28 } 29 int n; 30 while(scanf("%d",&n)==1){ 31 scanf("%s",str); 32 33 if(n%2){ 34 printf("0\n"); continue; 35 } 36 LL m = n/2; 37 int len =strlen(str); 38 LL L=0,R=0; 39 for(int i=0; i<len; ++i){ 40 if(str[i]==‘(‘) L++; 41 else if(str[i]==‘)‘)R++; 42 if(L<R){ 43 L=-1; break; 44 } 45 } 46 if(L==-1||L>m){ 47 printf("0\n");continue; 48 } 49 if(L==R&&L+R==n){ 50 printf("1\n");continue; 51 } 52 L=m - L; 53 R=m - R; 54 LL d0 = L; 55 L=R; R=d0; 56 LL d1 = inv(L+1,mod); 57 58 LL d2 = inv(dp[L],mod); 59 LL d3 = inv(dp[R],mod); 60 61 LL ans =( ( ( ( ( ( ( ( L-R+1 )*d1 )%mod) * d2 )%mod) * d3)%mod) * dp[L+R])%mod; 62 printf("%I64d\n",ans); 63 } 64 65 return 0; 66 }
标签:
原文地址:http://www.cnblogs.com/Opaser/p/4337646.html