题解 P7044 【「MCOI-03」括号】
littleKtian · · 题解
一个括号串的
设子串
利用组合数知识可知答案为:
直接枚举
利用后缀和可以做到
#include<bits/stdc++.h>
using namespace std;
#define p 998244353
#define N 2000000
int jc[N+5],ny[N+5];
int c[1000005],r[1000005];
int z[1000005],zd,rp[1000005],l;
int n,k,ans,lans;
int C(int x,int y){return 1ll*jc[x]*ny[y]%p*ny[x-y]%p;}
int main()
{
jc[0]=ny[0]=ny[1]=1;
for(int i=1;i<=N;i++)jc[i]=1ll*i*jc[i-1]%p;
for(int i=2;i<=N;i++)ny[i]=1ll*(p-p/i)*ny[p%i]%p;
for(int i=1;i<=N;i++)ny[i]=1ll*ny[i]*ny[i-1]%p;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
char ch=getchar();
while(ch!='('&&ch!=')')ch=getchar();
c[i]=ch=='('?1:0;
}
for(int i=1;i<=n;i++)r[i]=C(n-i+k-1,k-1);
for(int i=1;i<=n;i++)
{
if(c[i])z[++zd]=i;
else if(zd)rp[z[zd--]]=i;
else ++l;
lans=(lans+1ll*r[i]*(zd+l))%p;
}
for(int i=n;i;i--)r[i]=(r[i]+r[i+1])%p;
for(int i=1;i<=n;i++)
{
ans=(ans+1ll*C(i+k-2,k-1)*lans)%p,lans=(lans-r[i]+p)%p;
if(rp[i])lans=(lans+1ll*2*r[rp[i]])%p;
}
printf("%d",ans);
}