Codeforces785D - Anton and School - 2
传送门
题意
给出一个只包含'(',')'的字符序列,询问有多少个\(RSBS\)
分析
首先需要知道一个公式
\[\sum_{i=0}^{min(x,y)}C_x^i*C_y^i=C_{x+y}^x
\]
接下来我们观察第i个'(',假设它左边有x个'(',右边有y个')',那么包含它的RSBS有多少个?答案是\(C_{x+y-1}^x\),因为它已经“消耗了”一个')',所以左边的'('只能与右边的y-1个')'匹配。最后扫一遍即可。
代码
#include<bits/stdc++.h>
const int N = 400010;
const int moder = 1e9 + 7;
int fac[N], inv[N];
char s[N];
int power_mod(int a, int index){
int ret = 1;
while (index){
if (index & 1){
ret = 1ll * ret * a % moder;
}
a = 1ll * a * a % moder;
index >>= 1;
}
return ret;
}
int calc(int x, int y){
return 1ll * fac[x + y - 1] * inv[y - 1] % moder * inv[x] % moder;
}
void init()
{
fac[0] = 1;
for (int i = 1; i < N; ++ i){
fac[i] = 1ll * fac[i - 1] * i % moder;
}
inv[N - 1] = power_mod(fac[N - 1], moder - 2);
for (int i = N - 2; i >= 0; -- i){
inv[i] = 1ll * inv[i + 1] * (i + 1) % moder;
}
}
int main(){
init();
scanf("%s", s);
int cnt2 = 0, len = strlen(s);
for (int i = 0; i < len; ++ i){
if (s[i] == ')'){
++ cnt2;
}
}
int cnt1 = 0, ans = 0;
for (int i = 0; i < len; ++ i){
if (s[i] == ')'){
-- cnt2;
continue;
}
++ cnt1;
ans = (ans + calc(cnt1, cnt2)) % moder;
}
return printf("%d\n", ans), 0;
}
一直地一直地往前走