首页 > 代码库 > CodeForces 785D Anton and School - 2 组合数学

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 */

 

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