首页 > 代码库 > 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 组合数学
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。