题意:
问你一共有多少个子串,满足下列条件:
①长度为偶数
②前一半是(
③后一半是)
④子串不必要连续。
题解:我们O(n)枚举分界线,那么对应左侧有n个(,右边有m个)
则答案为C(i,n)*C(i,m)。
而由范德蒙不等式可得结果。
PS:求组合数时可以先将所有阶乘都预处理出来,在直接求即可
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const ll maxn = 2e5 + 10;
const ll MOD = 1e9 + 7;
char s[maxn];
ll fac[maxn];
ll q_pow(ll x, ll k){
if(k == 0) return 1;
if(k == 1) return x;
ll temp = q_pow(x,k/2);
ll ans = temp * temp % MOD;
if(k % 2) ans = ans * x % MOD;
return ans;
}
ll rev(ll x){
return q_pow(x,MOD - 2);
}
ll C(ll k, ll n){
ll ans = 1;
ans = fac[n];
ans = ans * rev(fac[k]) % MOD;
ans = ans * rev(fac[n - k]) % MOD;
return ans;
}
int main()
{
fac[0] = 1;
for(int i = 1;i <= maxn - 10;i++) fac[i] = fac[i - 1] * i % MOD;
ll cntl = 0,cntr = 0;
scanf("%s",s);
ll len = strlen(s),ans = 0;
for(ll i = 0;i < len;i++) if(s[i] == ')') cntr++;
for(ll i = 0;i < len;i++){
if(s[i] == '(') {
ans = (C(cntr - 1,cntl + cntr) + ans) % MOD;
cntl++;
}
else if(s[i] == ')') cntr--;
}
printf("%I64d\n",ans % MOD);
return 0;
}