题解 CF1654H Three Minimums

更好的阅读体验

题意简述

给出长 m 的不等号序列 s,求长度为 n 的排列 p 个数,使得:

  • 对于所有 1l<rn,rl>1 且最小值与次小值在区间两端的区间,区间内第三小值为 pl+1pr1

  • 对于所有 t[1,m],若 st=<,则 pt<pt+1;否则 pt>pt+1

答案对 998244353 取模。

n2×105,m100


题目分析

标记记号 check[i,<]=[i>msi=<]check[i,<]=[i>msi=>]

考虑一个序列是否是好的:

  • 1 不在两端,设 pi=1,则 p[1:n] 合法当且仅当 p[1:i]p[i:n] 合法;

  • 1 在两端(不妨设 p1=1):

    • 2 不在另一端,设 pj=2,则 p[1:n] 合法当且仅当 p[1:j]p[j:n] 合法。

    • 否则 pn=2,则 p[1:n] 合法当且仅当 「p2=3p[2:n] 是好的」 或者 「pn1=3p[1:n1] 是好的」。

于是设计一个区间 DP。设 a(l,r),a1(l,r),a1(l,r),a12(l,r),a21(l,r) 分别表示对于区间 (l,r),满足给定条件的「区间两端无限制」,「区间左端点为最小值」,「区间右端点为最小值」,「区间左端点为最小值,右端点为次小值」,「区间左端点为次小值,右端点为最小值」的方案数。于是有:

a(l,r)=i=lra1(l,i)a1(i,r)(rlil)

a1(t,t)=1,a1(l,r)=i=l+1ra12(l,i)a1(i,r)(rl1il1)

a1(t,t)=1,a1(l,r)=i=lr1a1(l,i)a21(i,r)(rl1il)

a12(t,t+1)=check[t,<],a12(t,t+2)=check[t,<]check[t+1,>],a12(l,r)=check[l,<]a21(l+1,r)+check[r1,>]a12(l,r1)

a21(t,t+1)=check[t,>],a21(t,t+2)=check[t,<]check[t+1,>],a21(l,r)=check[l,<]a21(l+1,r)+check[r1,>]a12(l,r1)

暴力做时间复杂度 O(n3),无法接受。


答案为 a(1,n),故要对所有 k[k,n] 计算出 a1(1,k)a1(k,n)

  • Part 1a1(1,k)

DP 式为 a1(1,1)=1a1(1,k)=i=1k1a1(1,i)a21(i,k)(k2i1)

观察到给左右两边的 a1 同乘阶乘会使形式简化许多。设 a1(1,k)=(k1)!xk1,x0=1,则有:

(k1)!xk1=i=1k1(i1)!xi1a21(i,k)(k2)!(i1)!(ki1)!

(k1)xk1=i=1k1xi1a21(i,k)1(ki1)!

kxk=i=1kxi1a21(i,k+1)1(ki)!

kxk=i=0k1xia21(i+1,k+1)(ki1)!

这个形式很好看,但是 a21(i+1,k+1) 有两个变量而难以处理。

注意到限制只在前 m 位处,故对于 l>m 的状态,其 DP 值只与长度 rl+1 有关。设 b??(k)=a??(m+1,m+k)。上式就可以改写为:

kxk=i=0k1xib21(ki+1)(ki1)!+i=0min(k1,m1)xia21(i+1,k+1)b21(ki+1)(ki1)!

ui=b21(i+2)i!vk1=i=0min(k1,m1)xia21(i+1,k+1)b21(ki+1)(ki1)!。则:

kxk=vk1+i=0k1xiuki1

写成生成函数就是 X=V+UX,解这个微分方程得到 X=exp(U)[1+(Vexp(U))]

注意到 b21(k)=2k2+[k=1],对所有 l[1,m+1]r(l,n] 暴力 DP 出 a21(l,r) 即可得到 b21(k),再对所有 t[1,m] 暴力 DP 得到 xt,即可计算 UV

  • Part 2a1(k,n)

注意到 k>ma1(k,n)=b1(nk+1),考虑先求出 b1(k),求出后可对 k[1,m] 暴力 DP 出 a1(k,n)

DP 式为 a1(n,n)=1,a1(k,n)=i=k+1na12(k,i)a1(i,n)(nk1ik1),即:

b1(k)=i=2kb12(i)b1(ki+1)(k2i2)=i=1k1b1(i)b12(ki+1)(k2i1)

b1(k)=(k1)!yk1,代入:

(k1)!yk1=i=1k1(i1)!yi1b12(ki+1)(k2)!(i1)!(ki1)!

(k1)yk1=i=1k1yi1b12(ki+1)(ki1)!

kyk=i=1kyi1b12(ki+2)(ki)!

kyk=i=0k1yib12(ki+1)(ki1)!=i=0k1yiuki1

于是有 Y=UY,解得 Y=exp(U)

总时间复杂度 O(n(logn+m))


代码

...
long long n,m,ans;
char S[N];
bool ck(long long pos,bool id){
if(pos>m) return 1;
return id==(S[pos]=='>');
}
long long a12[M][O],a21[M][O],a_1[N],a1_[N],b12[N],b21[N],b1_[N];
long long x[N],U[N],V[N],P[N],Q[N],F[N];
int main(){
init(N-5);
cin>>n>>m;
scanf("\n%s",S+1);
for(long long l=1;l<=n;l++){
for(long long i=1;i+l-1<=n && i<=m+1;i++){
long long j=i+l-1;
if(j==i+1) a12[i][i+1]=ck(i,0);
else if(j==i+2) a12[i][j]=ck(i,0)*ck(j-1,1);
else a12[i][j]=(ck(i,0)*((i==m+1)?pw[j-(i+1)-2]:a21[i+1][j])%mod+ck(j-1,1)*a12[i][j-1]%mod)%mod;
if(j==i+1) a21[i][i+1]=ck(i,1);
else if(j==i+2) a21[i][j]=ck(i,0)*ck(j-1,1);
else a21[i][j]=(ck(i,0)*((i==m+1)?pw[j-(i+1)-2]:a21[i+1][j])%mod+ck(j-1,1)*a12[i][j-1]%mod)%mod;
}
}
//a12/a21[1,m+1][1,n]
for(long long i=1;i<=n-m;i++) b12[i]=a12[m+1][m+i],b21[i]=a21[m+1][m+i];
x[0]=1;
for(long long i=1;i<=m;i++){
for(long long j=0;j<i;j++) x[i]=(x[i]+x[j]*a21[j+1][i+1]%mod%mod*inv[i-j-1]%mod)%mod;
x[i]=x[i]*invv[i]%mod;
}
//x[1,m]
for(long long i=0;i<=n+1;i++){
U[i]=b21[i+2]*inv[i]%mod;
if(i) for(long long j=0;j<=min(i-1,m-1);j++)
V[i-1]=(V[i-1]+x[j]*(a21[j+1][i+1]+mod-b21[i+1-j])%mod*inv[i-j-1]%mod)%mod;
}
//U/V[0,n]
poly::Limit(U,U,n);
poly::Exp(P,U,n);
INV::solve(Q,P,n);
NTT::solve(V,V,Q,n,n);
poly::Limit(V,V,n);
V[0]=(V[0]+1)%mod;
NTT::solve(F,P,V,n,n);
//F/P
for(int i=1;i<=n;i++) a_1[i]=F[i-1]*mul[i-1]%mod,b1_[i]=P[i-1]*mul[i-1]%mod;
for(int i=m;i>=1;i--)
for(long long t=i+1;t<=n;t++)
a1_[i]=(a1_[i]+a12[i][t]*((t>m)?b1_[n-t+1]:a1_[t])%mod*C(n-i-1,t-i-1)%mod)%mod;
//a1_[1,m][n]
for(int i=1;i<=n;i++) ans=(ans+a_1[i]*((i>m)?b1_[n-i+1]:a1_[i])%mod*C(n-1,i-1)%mod)%mod;
cout<<ans;
}
posted @   苹果蓝17  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示