CF1264D2 Beautiful Bracket Sequence (hard version)

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

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

这个位置的贡献为:

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

考虑我们拆项。

(lsum_{i = 0} ^ xinom{x}{i}inom{y}{l + i - r} + sum_{i = 0} ^ x iinom{x}{i}inom{y}{l + i - r})

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

那么一个点的贡献是(linom{x + y}{r + y - l} + xinom{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;
}
原文地址:https://www.cnblogs.com/dixiao/p/15160643.html