【学习笔记】CF1264D2 Beautiful Bracket Sequence (hard version)

news/2024/11/8 3:46:45/

考虑固定一种计算贡献的方式,从而构造组合意义。

问题接踵而至。如何计算 ( i , j ) (i,j) (i,j)在所有方案中产生贡献的次数?从内往外考虑,那么要求 [ l , i ] [l,i] [l,i]中的左括号和 [ j , r ] [j,r] [j,r]中的右括号数目相等,不难发现这个限制是充要的。又因为问的就是整个序列的权值,所以设 [ 1 , i ] [1,i] [1,i]中有 a a a个问号, [ j , n ] [j,n] [j,n]中有 b b b个问号,左右括号相差的数目为 k k k,那么方案数 ∑ i ≤ a ( a i ) ( b i − k ) = ∑ i ≤ a ( a a − i ) ( b i − k ) = ( a + b a − k ) \sum_{i\le a}\binom{a}{i}\binom{b}{i-k}=\sum_{i\le a}\binom{a}{a-i}\binom{b}{i-k}=\binom{a+b}{a-k} ia(ia)(ikb)=ia(aia)(ikb)=(aka+b),显然如果对组合数比较熟悉的话是不难推出这个式子的。注意, [ i , j ] [i,j] [i,j]这段序列长什么样子事实上并不影响答案。

怎么优化这个枚举过程呢?显然是固定左端点,唯一需要注意的细节是当左右两边的问号都被确定时,此时右端点的选取是唯一的,也就是说恰好对应一种方案,那么将等号改成不等号就有: ∑ i ≤ a ∑ j ≥ i − k ( b j ) ( a i ) \sum_{i\le a}\sum_{j\ge i-k}\binom{b}{j}\binom{a}{i} iajik(jb)(ia),我们希望 j j j 0 0 0开始枚举,因此不妨变一下形式: ∑ i ≤ a ∑ j ≥ 0 ( b i − k + j ) ( a a − i ) \sum_{i\le a}\sum_{j\ge 0}\binom{b}{i-k+j}\binom{a}{a-i} iaj0(ik+jb)(aia),交换求和顺序就有: ∑ j ≥ 0 ∑ i ≤ a ( b i − k + j ) ( a a − i ) = ∑ j ≥ 0 ( a + b a − k + j ) \sum_{j\ge 0}\sum_{i\le a}\binom{b}{i-k+j}\binom{a}{a-i}=\sum_{j\ge 0}\binom{a+b}{a-k+j} j0ia(ik+jb)(aia)=j0(ak+ja+b),注意到 a + b a+b a+b是定值,于是就做完了。

复杂度 O ( n ) O(n) O(n)

感觉组合数的运算还是比多项式要轻量级的。

#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define db double
using namespace std;
const int mod=998244353;
const int N=1e6+5;
int n,m,K,sum1,sum2,sum3,a,b;
ll fac[N],inv[N],f[N],f2[N],res;
string s;
ll fpow(ll x,ll y=mod-2){ll z(1);for(y;y>>=1;){if(y&1)z=z*x%mod;x=x*x%mod;}return z;
}
void add(ll &x,ll y){x=(x+y)%mod;}
ll binom(int x,int y){if(x<0||y<0||x<y)return 0;return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
void init(int n,int m){fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;inv[n]=fpow(fac[n]);for(int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;for(int i=m;i>=0;i--)f[i]=f[i+1],add(f[i],binom(m,i));for(int i=m-1;i>=0;i--)f2[i]=f2[i+1],add(f2[i],binom(m-1,i));
}
signed main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>s,n=s.size();for(int i=0;i<n;i++)if(s[i]=='?')m++;init(n,m);for(int i=0;i<n;i++)sum1+=(s[i]==')');for(int i=0;i<n-1;i++){sum2+=(s[i]=='('),sum1-=(s[i]==')'),sum3+=(s[i]=='?');if(s[i]=='('){K=sum1-sum2;a=sum3,b=m-sum3;assert(a>=0),assert(b>=0);assert(a+b==m);add(res,f[max(0,a-K)]);}else if(s[i]=='?'){K=sum1-sum2-1;a=sum3-1,b=m-sum3;assert(a>=0),assert(b>=0);assert(a+b==m-1);add(res,f2[max(0,a-K)]);}}cout<<res;
}

http://www.ppmy.cn/news/404044.html

相关文章

跨越时空的教育:在线培训系统的全球化

随着全球化的发展&#xff0c;跨越时空的教育已经成为现实。在线培训系统可以打破地域限制&#xff0c;让学生能够接受来自世界各地的教育资源。这种新型教育模式具有巨大的潜力和优势。 在线培训系统是指通过互联网提供的远程教育服务。它可以通过网络平台、视频教育、虚拟课…

水。

最近水了好多水题&#xff0c;都觉得自己变水了...... 转载于:https://www.cnblogs.com/hoskey/p/3733237.html

水一下?!

啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊aa

水环境与水生态的区别

水环境关注的方面 水质情况、底质污染情况、污染源情况、水体自净能力、水环境容量&#xff08;污染负荷&#xff09;、水功能区、水体营养状况&#xff08;湖库&#xff09;&#xff0c;水环境治理工程&#xff0c;水利工程对环境的影响&#xff1b; 水生态关注的方面 河湖生态…

水一下水一下

水一下水一下水一下

水水

水水说&#xff1a;水我认为是比较干净纯洁 也是很简单的 和我一样&#xff08;2006-06-15 22:53:10&#xff09;

水文章(bushi)

这篇水文章主要呢是用来记录我到CSDN两个月了&#xff0c;来跟大家来分享一下我的感受 进站 我是八月中入站的&#xff0c;当时的我只是一个啥都不会的小白&#xff0c;也没有想学编程的欲望&#xff0c;偶然的一次机会我在网上搜东西是按了一下CSDN的网站&#xff0c;一进来…