Codeforces 785D Anton and School - 2(推公式+乘法原理+组合数学)

题目链接 Anton and School - 2

对于序列中的任意一个单括号对(),

左括号左边(不含本身)有a个左括号,右括号右边(不含本身有)b个右括号。

那么答案就为

但是这样枚举左右的()的话,最快情况复杂度为1e10,TLE。
所以对于每个左括号,把他右边的所有右括号一起来考虑。
对于每个左括号,令它左边(不含它本身)括号数位x,它右边右括号数位y。
那么当前答案为
 
 
复杂度O(Nlogmod),其中mod=1e9+7.
PS:代码中的这个y应该是上图的y-1.
 
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define rep(i, a, b)              for(int i(a); i <= (b); ++i)
 6 #define dec(i, a, b)              for(int i(a); i >= (b); --i)
 7 
 8 #define LL      long long
 9 
10 const int N     =    200000      +       10;
11 
12 const LL mod = 1000000007;
13 
14 LL c[N], f[N];
15 char s[N];
16 int n;
17 LL ans = 0;
18 LL fac[300010];
19 
20 inline LL Pow(LL a, LL b, LL Mod){ LL ret(1); for (; b; b >>= 1, (a *= a) %= Mod) if (b & 1) (ret *= a) %= Mod; return ret;}    
21 
22 inline LL C(LL n, LL m){ return m > n ? 0 : fac[n] * Pow(fac[m] * fac[n - m] % mod, mod - 2, mod) % mod; }
23 
24 int main(){
25 
26     scanf("%s", s + 1);
27     n = strlen(s + 1);
28     
29     fac[0] = 1; rep(i, 1, 200010) fac[i] = (fac[i - 1] * i) % mod;
30 
31     memset(c, 0, sizeof c);
32     memset(f, 0, sizeof f);
33     rep(i, 1, n) if (s[i] == '(') c[i] = c[i - 1] + 1; else c[i] = c[i - 1];
34     dec(i, n, 1) if (s[i] == ')') f[i] = f[i + 1] + 1; else f[i] = f[i + 1];
35 
36     rep(i, 1, n) if (s[i] == '('){
37         LL x = c[i] - 1, y = f[i + 1] - 1;
38         
39         
40         (ans += C(x + y + 1, x + 1)) %= mod;
41     }
42 
43     cout << ans << endl;
44     return 0;
45 
46 }

 

 
 
 

 

posted @ 2017-03-23 21:25  cxhscst2  阅读(348)  评论(0编辑  收藏  举报