[CF1178F1]Short Colorful Strip

题目

传送门

题解

题目所要求的是从小到大染色,我们不妨顺着这个顺序对方案数进行统计

\(f[l][r]\)区间 \([l,r]\) 目前颜色一致(不然无法进行染色),将 \([l,r]\) 染成目标状态的方案数,由于我们先染最小编号的颜色,不妨记最小颜色的编号为 \(p\),这个 \(p\) 可以预处理出来:

inline void Solve_p(){
    int minn;
    rep(i,1,n)rep(j,i,n){
        minn=INF;
        rep(k,i,j)if(c[k]<minn)
            minn=c[k],p[i][j]=k;
    }
}

枚举最小颜色填入的区间为 \([i,j]\),而最后位置 \(p\) 要和目标状态一致,即保持为最小的颜色,那么我们所枚举的这个 \([i,j]\) 一定要使 \(p\in [i,j]\),不然无法保证和目标状态一致。

而后,由于 \([l,p-1]\)\([p+1,j]\) 都要染成其他的颜色,而我们目前已经将 \([i,j]\) 染成最小颜色,所以我们整理一下区间 \([l,r]\) 中有哪些区间同色,可以继续染色:\([i,j]\)\([l,i-1]\)\([j+1,r]\),而我们要保证点 \(p\) 不然成其他颜色,所以要将 \(p\)\([i,j]\) 中去掉,那么就是以下四个区间:

\[[l,i-1],[i,p-1],[p+1,j],[j+1,r] \]

由排列组合,我们最后的转移即为

\[f[l][r]=\sum_{i=l}^{p}\sum_{j=p}^{r}f[l][i-1]\times f[i][p-1]\times f[p+1][j]\times f[j+1][r] \]

注:此处定义当 \(i>j\) 时,\(f[i][j]=1\)

显然这个做法是 \(\mathcal O(n^4)\) 的,考虑对转移进行变换

\[f[l][r]=\sum_{j=p}^{r}f[p+1][j]\times f[i][p-1]\times \left [\sum_{i=l}^{p}f[l][i-1]\times f[j+1][r] \right ] \]

发现前一半和后一半独立,那么我们只需记 \(sum[l][r]=\sum_{i=l}^{p}f[l][i-1]\times f[j+1][r]\),显然这个 \(sum\) 可以 \(\mathcal O(n)\) 处理,那么转移为

\[f[l][r]=sum[l][r]\times\left [ \sum_{j=p}^{r}f[p+1][j]\times f[i][p-1] \right ] \]

这个就可以 \(\mathcal O(n)\) 做了,总体即为 \(\mathcal O(n^3)\)

对于最开始的情况,所有点都是颜色 \(0\),故 dfs(1,n)

代码

#include<cstdio>
#include<cstring>

#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
typedef long long LL;
// typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
// #define int long long
// #define int unsigned
// #define int unsigned long long

#define cg (c=getchar())
template<class T>inline void read(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T>inline T read(const T sample){
    T x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);
    putchar(x%10^48);
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
    inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int MAXN=500;
const int MOD=998244353;
const int INF=0x3f3f3f3f;

int n,m,c[MAXN+5];
int f[MAXN+5][MAXN+5];
int p[MAXN+5][MAXN+5];

inline void Init(){
    n=read(1),m=read(1);
    rep(i,1,n)c[i]=read(1);
}

inline void Solve_p(){
    int minn;
    rep(i,1,n)rep(j,i,n){
        minn=INF;
        rep(k,i,j)if(c[k]<minn)
            minn=c[k],p[i][j]=k;
    }
    // rep(i,1,m)rep(j,i,n){
    //     printf("p[%d, %d] == %d\n",i,j,p[i][j]);
    // }
}

int sum[MAXN+5][MAXN+5];
int Dfs(const int l,const int r){
    // printf("Now l == %d, r == %d\n",l,r);
    if(l>r)return 1;
    if(f[l][r]!=-1)return f[l][r];
    f[l][r]=0;
    rep(i,l,p[l][r]){
        sum[l][r]=sum[l][r]+1ll*Dfs(l,i-1)*Dfs(i,p[l][r]-1)%MOD;
        if(sum[l][r]>=MOD)sum[l][r]-=MOD;
    }
    rep(j,p[l][r],r){
        f[l][r]=f[l][r]+1ll*Dfs(p[l][r]+1,j)*Dfs(j+1,r)%MOD*sum[l][r]%MOD;
        if(f[l][r]>=MOD)f[l][r]-=MOD;
    }
    return f[l][r];
}

signed main(){
    Init();
    Solve_p();
    memset(f,-1,sizeof f);
    writc(Dfs(1,n),'\n');
    // rep(i,1,n)rep(j,i,n){
    //     printf("f[%d, %d] == %d\n",i,j,f[i][j]);
    // }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Arextre/p/13393333.html