CF1264D2 Beautiful Bracket Sequence (hard version)

考虑\(D1\)\(O(n^2)\),我们直接进行组合处理。

考虑在\(p\)这个位置,左边有\(l\)个(,右边有\(r\)个),左边有\(l\)个问号,右边有\(r\)个问号。

这个位置的贡献为:

\(\sum_{i = 0} ^ x (l+i)\binom{x}{i}\binom{y}{l + i - r}\)

考虑我们拆项。

\(l\sum_{i = 0} ^ x\binom{x}{i}\binom{y}{l + i - r} + \sum_{i = 0} ^ x i\binom{x}{i}\binom{y}{l + i - r}\)

考虑前者可以写作\(l\binom{x + y}{r + y - l}\)
后者把\(i\)吸收进去,\(x\)提取出来
\(x\binom{x + y - 1}{r + y - l - 1}\)

那么一个点的贡献是\(l\binom{x + y}{r + y - l} + x\binom{x + y - 1}{r + y - l - 1}\)

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long 
#define N 1000005
#define mod 998244353

ll l[N],r[N],cnt[N];

char a[N];

ll s[(N << 1) + 10],inv[(N << 1) + 10];

inline ll pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b & 1)ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}

inline ll C(ll x,ll y){
	if(x < y || x < 0 || y < 0)return 0; 
	return s[x] * inv[y] % mod * inv[x - y] % mod;
}

int main(){
	scanf("%s",a + 1);
	ll n = std::strlen(a + 1);
	s[0] = 1;
	for(int i = 1;i <= N << 1;++i)
	s[i] = s[i - 1] * i % mod;
	inv[N << 1] = pow(s[N << 1],mod - 2);
	for(int i = (N << 1) - 1;i >= 0;--i)
	inv[i] = (i + 1) * inv[i + 1] % mod;
	l[0] = r[0] = cnt[0] = 0; 
	for(int i = 1;i <= n;++i){
		l[i] = l[i - 1];
		r[i] = r[i - 1];
		cnt[i] = cnt[i - 1];
		if(a[i] == '(')
		l[i] ++ ;
		if(a[i] == ')')
		r[i] ++ ;
		if(a[i] == '?')
		cnt[i] ++ ;
	}
	ll ans = 0;
	for(int i = 1;i <= n;++i){
		ll li = l[i] - l[0];
		ll ri = r[n] - r[i];
		ll x = cnt[i] - cnt[0];
		ll y = cnt[n] - cnt[i];
		ans = (ans + li * C(x + y,ri + y - li) % mod + x * C(x + y - 1,ri + y - li - 1) % mod) % mod;
	}
	std::cout<<ans<<std::endl;
}
posted @ 2021-08-19 10:44  fhq_treap  阅读(54)  评论(0编辑  收藏  举报