Codeforces 1264D - Beautiful Bracket Sequence(組合數學)
阿新 • • 發佈:2021-08-11
發現性質+組合恆等式
每往後移一格,\(x-y\) 就會恰好增加 \(1\),也就是說必然恰好存在一個斷點滿足 \(x=y\),在此之前,\(x<y\),因此 \(\min(x,y)=x\),在此之後,\(x>y\),因此 \(\min(x,y)=y\),又因為 \(x\) 隨 \(i\) 的增大單調不增,\(y\) 隨 \(i\) 的增大單調不降,因此在這個斷點前必然有 \(\min(x,y)<\) 斷點處的 \(x\),在這個斷點之後必然有 \(\min(x,y)>\) 斷點處的 \(x\),因此這個斷點處的 \(x\) 就是該括號序列所有由一段左括號+一段右括號組成的合法括號序列中,深度最大的那一個,也就是說:
首先對於這樣的題目,我們應先考慮如何計算一個括號序列 \(s\) 的權值。一件非常顯然的事情是,在深度最深的、是原括號序列的子序列的括號序列中,必定存在一個滿足前面只由一段左括號,後面只由一段右括號組成,因此我們考慮列舉這中間位置在原括號序列中對應哪個位置,那麼假設這個斷點位於 \(i\) 和 \(i+1\) 之間,我們設 \(i\) 及之前有 \(x\) 個左括號,\(i+1\) 及之後有 \(y\) 個右括號,那麼顯然以這個位置為端點的括號序列的深度就是 \(\min(x,y)\),注意到這裡涉及一個 \(\min\),一臉不好直接維護的樣子,不過注意一件事情,那就是你這個 \(i\)
Conclusion. 一個括號序列的權值,等於其所有相鄰位置 \(i,i+1\) 中,滿足 \(i\) 及之前左括號個數等於 \(i+1\) 之後的右括號個數的 \(i\) 之前的左括號個數。
接下來此題就變成一個組合數學問題了,考慮列舉這個斷點 \(i\),假設 \(i\) 前面問號個數為 \(a\),左括號個數為 \(b\),\(i+1\) 後面問號個數為 \(c\),右括號個數為 \(d\),那麼這個點的貢獻為:
\[\sum\limits_{i=0}^a(i+b)\dbinom{a}{i}\dbinom{c}{i+b-d} \]然後括號拆拆,組合恆等式推推:
\[\begin{aligned} &\sum\limits_{i=0}^a(i+b)\dbinom{a}{i}\dbinom{c}{i+b-d}\\ =&\sum\limits_{i=0}^ai\dbinom{a}{i}\dbinom{c}{i+b-d}+b\sum\limits_{i=0}^a\dbinom{a}{i}\dbinom{c}{i+b-d}\\ =&\sum\limits_{i=0}^aa\dbinom{a-1}{i-1}\dbinom{c}{i+b-d}+b\sum\limits_{i=0}^a\dbinom{a}{i}\dbinom{c}{i+b-d}\\ =&a\sum\limits_{i=0}^a\dbinom{a-1}{a-i}\dbinom{c}{i+b-d}+b\sum\limits_{i=0}^a\dbinom{a}{a-i}\dbinom{c}{i+b-d}\\ =&a\dbinom{a-1+c}{a+b-d}+b\dbinom{a+c}{a+b-d} \end{aligned} \]預處理一下簡單算算即可。
const int MAXN=1e6;
const int MOD=998244353;
char s[MAXN+5];int n;
int fac[MAXN*2+5],ifac[MAXN*2+5];
void init_fac(int n){
for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i]*ifac[i-1]%MOD;
}
int binom(int x,int y){
if(x<0||y<0||x<y) return 0;
return 1ll*fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;
}
int main(){
scanf("%s",s+1);n=strlen(s+1);init_fac(MAXN+5);int s1=0,s2=0,ans=0;
for(int i=1;i<=n;i++) s1+=(s[i]==')'),s2+=(s[i]=='?');
for(int i=1,x=0,l=0,c=0;i<=n;i++){
x+=(s[i]=='?');l+=(s[i]=='(');c+=(s[i]==')');int y=s2-x,r=s1-c;
ans=(ans+1ll*l*binom(x+y,y+r-l)+1ll*x*binom(y+x-1,y-l+r-1))%MOD;
} printf("%d\n",ans);
return 0;
}