1. 程式人生 > >CodeForces 785D Anton and School - 2 組合數學

CodeForces 785D Anton and School - 2 組合數學

school log cer sin 位置 mem cin typedef pair

題意:

給你一串括號 問你有多少種匹配的子串

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

思路:

首先我們預處理

當前位置之前有多少左括號 和 當前位置之後有多少右括號

對於每一個處於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 組合數學