「CF1874F-Jellyfish and OEIS」题解

F. Jellyfish and OEIS

sol

一个区间不是一个排列不太好做,考虑反向容斥,考虑钦定一个区间为一个排列。

但直接这么做还是很困难,然而本题存在一个性质,两个区间交叉的部分,其容斥系数可以抵消,也就是可以不考虑相交的区间。感性理解一下,是正确的。

那么我们钦定的区间就具有如下位置关系:要么包含,要么不交。这样容斥会方便许多,记钦定的区间集合为 \(S\),容斥系数即为 \((-1)^{|S|}\)

\(f_{l,r}\) 表示区间 \([l,r]\)\([l,r]\) 的一个排列时带容斥系数的方案数,\(g_{l,r,x}\) 表示区间 \([l,r]\) 内含有 \(x\) 个散点的带容斥系数的方案数,实现上由于散点任意排列的方案数即为 \(x!\) 易求,计算 \(g\) 时可以忽略这个系数,转移时乘上即可。

按区间长度升序进行区间 DP,存在下述几种转移方式:

  • 左端点为散点,有 \(g_{l,r,x}\gets g_{l,r,x}+g_{l+1,r,x-1}\)
  • 区间 \([l,k]\) 被钦定为 \([l,k]\) 的排列,满足 \(k\le m_l\land k<r\),有 \(g_{l,r,x}\gets g_{l,r,x}-f_{l,k}g_{k+1,r}\)
  • 我们先计算出 \(f_{l,r}=\sum\limits_xx!g_{l,r,x}\)
  • \(r\le m_l\)\(g_{l,r,0}\gets g_{l,r,0}-f_{l,r}\)

额外解释一下最后两步,\(f_{l,r}\) 是钦定区间 \([l,r]\)\([l,r]\) 的排列的方案数,而 \(g_{l,r,0}\) 并不要求区间 \([l,r]\)\([l,r]\) 的排列,因此 \(g_{l,r,0}\) 要更新上 \(f_{l,r}\)\(f_{l,r}\) 无需额外的更新。

最后需要特判 \(m_1=n\) 的情况,此时无解。否则答案即为 \(f_{1,n}\)

code

const int N=205;

int n;
int m[N];
mint fc[N],iv[N];
mint f[N][N],g[N][N][N];

inline void Main(){
    cin>>n;
    fc[0]=1;rep(i,1,n)fc[i]=fc[i-1]*i;
    rep(i,1,n)cin>>m[i];
    rep(i,0,n)g[i+1][i][0]=1;
    rep(l,1,n)rep(i,1,n-l+1){
        int j=i+l-1;
        rep(x,1,j-i+1)g[i][j][x]+=g[i+1][j][x-1];
        rep(k,i,min(m[i],j-1))rep(x,0,j-k)g[i][j][x]-=f[i][k]*g[k+1][j][x];
        rep(x,0,j-i+1)f[i][j]+=g[i][j][x]*fc[x];
        if(j<=m[i])g[i][j][0]-=f[i][j];
    }
    if(m[1]==n)return put(0),void();
    put(f[1][n]);
}
posted @ 2025-08-18 21:45  LastKismet  阅读(13)  评论(0)    收藏  举报