CodeForces 785D Anton and School - 2 组合数学

题意:

给你一串括号 问你有多少种匹配的子串

就是前半部分都是‘(‘ 后半部分都是‘)‘的子串

思路:

首先我们预处理

当前位置之前有多少左括号 和 当前位置之后有多少右括号

对于每一个处于i位置的左括号

我们将ans+=C(left[i]+right[i]-1,right[i]-1)

这个式子是C(i-1,left[i]-1)*C(i+1,right[i])化简来的

因为选的数总数是不变的 所以可以化简(?)

就是从左边选i-1个左括号 从右边选i+1个右括号

因为自己是必选的 所以左括号-1

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(a) cerr<<#a<<"=="<<a<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 typedef pair<int,int> pii;
 7
 8 const int maxn=2e5+10;
 9 const int mod=1e9+7;
10
11 ll fac[maxn];
12
13 ll quick_pow(ll a,ll n)
14 {
15     ll ans=1;
16     while(n)
17     {
18         if(n%2) ans=1ll*ans*a%mod;
19         a=1ll*a*a%mod;
20         n>>=1;
21     }
22     return ans;
23 }
24
25 ll inv(ll a)
26 {
27     return quick_pow(a,mod-2);
28 }
29
30 void init()
31 {
32     fac[0]=1;
33     for(int i=1;i<maxn;i++)
34     {
35         fac[i]=1ll*fac[i-1]*i%mod;
36     }
37 }
38
39 ll C(ll a,ll b)
40 {
41     ll ans=1;
42     if(a<b || b<0) return 0;
43     while(a&&b)
44     {
45         ll aa=a%mod,bb=b%mod;
46         if(aa<bb) return 0;;
47         ans = 1ll*ans*fac[aa]%mod * inv(1ll*fac[bb]*fac[aa-bb]%mod)%mod;
48         a/=mod,b/=mod;
49     }
50     return ans;
51 }
52
53 int main()
54 {
55     string str;
56     cin>>str;
57     int sz=str.size();
58     vector<int>left(sz,0),right(sz,0);
59     if(str[0]==‘(‘) left[0]=1;
60     for(int i=1;i<sz;i++)
61     {
62         left[i]=left[i-1]+(str[i]==‘(‘);
63     }
64     if(str[sz-1]==‘)‘) right[sz-1]=1;
65     for(int i=sz-2;i>=0;i--)
66     {
67         right[i]=right[i+1]+(str[i]==‘)‘);
68     }
69     ll ans=0;
70     init();
71     for(int i=0;i<sz;i++)
72     {
73         if(str[i]==‘(‘)
74         {
75             ans+=C(left[i]+right[i]-1,right[i]-1);
76             ans%=mod;
77         }
78     }
79     cout<<ans<<endl;
80     return 0;
81 }/*
82
83 )(()()
84
85 */
时间: 2024-10-11 21:28:21

CodeForces 785D Anton and School - 2 组合数学的相关文章

CodeForces 785D Anton and School - 2

枚举,容斥原理,范德蒙恒等式. 先预处理每个位置之前有多少个左括号,记为$L[i]$. 每个位置之后有多少个右括号,记为$R[i]$. 然后枚举子序列中第一个右括号的位置,计算这个括号的第一个右括号的方案数. 即在它左边取$k$个左括号,在右边取$k-1$个右括号都是合法的方案,这个东西可以用范德蒙恒等式化成一个组合数以及容斥原理计算. 范德蒙恒等式:http://blog.csdn.net/acdreamers/article/details/31032763 #include <cstdio

codeforces 785D D. Anton and School - 2

题目链接:http://codeforces.com/problemset/problem/785/D 题意:给你一个只包含'('和')'的字符串,然后问他的子序列中有多少满足前一半是左括号,后一半是右括号. 分析:看到题就想到是组合数学,对于一个左括号,他能影响到的右括号就是他后边的,因此,你需要求前缀和和后缀和,来这样来求组合数.现在我们枚举左括号,当枚举到他时,代表他一定被选,前缀和为n,后缀和为m,然后在他前边选i=0到min(n,m)-1个,在他后边选前边数+1个.然后就是C(n-1,

codeforces 785C Anton and Fairy Tale

题目链接:http://codeforces.com/problemset/problem/785/C 题意:仓库容量是n,一开始是满的,然后每天晚上可以往仓库里装m粮食,最多装到n.然后每天白天有鸟来吃粮食,一只鸟吃1单位.第i天有i只鸟.问你多少天鸟可以把粮食吃完. 分析:一开始读错题,导致wa了两发.如果n<=m的话,只有n只鸟的时候一天把他吃完,输出n.如果m<n的话,前m是肯定吃不完的,m天之后,从1开始计数,就是好比每天白天吃i+m,晚上装m,一天好比加了i.所以可以二分天数,但是

Codeforces 734C Anton and Making Potions(枚举+二分)

题目链接:http://codeforces.com/problemset/problem/734/C 题目大意:要制作n个药,初始制作一个药的时间为x,魔力值为s,有两类咒语,第一类周瑜有m种,每种咒语使制作一个药的时间变成a[i],花费b[i]的魔力,第二类咒语有k种,每种咒语瞬间产生c[i]个药,花费d[i]的魔力,c[i]和d[i]都是不递减的,求最短时间内产生n个药的时间.解题思路:因为c[i]和d[i]都是不降的,所以可以枚举a[i],然后二分查找花费小于t-b[i]的第二类咒语.注

codeforces 553A . Kyoya and Colored Balls 组合数学

Kyoya Ootori has a bag with n colored balls that are colored with k different colors. The colors are labeled from 1 to k. Balls of the same color are indistinguishable. He draws balls from the bag one by one until the bag is empty. He noticed that he

CodeForces 593B Anton and Lines

计算出每条线段在x1处的y坐标和x2处的y坐标. 就下来只要根据每条线段左右两处的y坐标就可以判断是否有交点. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; long long INF=9999999999999999; long long x1,x2; int n; struct X { long long k,b; l

CodeForces 734F Anton and School

位运算. 两个数的和:$A+B=(AandB)+(AorB)$,那么$b[i]+c[i]=n*a[i]+suma$.可以解出一组解,然后再按位统计贡献验证一下. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<v

CodeForces 734B Anton and Digits

贪心.先取$256$,再取$32$. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<

CodeForces 734E Anton and Tree

$dfs$缩点,树形$dp$. 首先将连通块缩点,缩点后形成一个黑白节点相间的树.接下来的任务就是寻找一个$root$,使这棵树以$root$为根,树的高度是最小的(也就是一层一层染色).树形$dp$可以解决这个问题,第一次$dfs$处理子树,第二次$dfs$枚举$root$计算答案. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring>