zoukankan      html  css  js  c++  java
  • CF1178F1 Short Colorful Strip

    XLV.CF1178F1 Short Colorful Strip

    考虑设\(f[i,j]\)表示:假设区间\([i,j]\)里面一开始所有格子的颜色都是相同的,那么,染成目标状态共有多少种染法。

    我们找到\([i,j]\)中最小的那个颜色,设为\(mp\)。则显然,我们下一步要染上\(mp\)这种颜色。

    设最终在位置\(p_{mp}\)上染上了颜色\(mp\)。则我们可以在所有这样的区间\([k,l]\)上染上\(mp\)\(i\leq k\leq p_{mp}\leq l\leq j\))。

    或许你会以为这意味着\(f[i,j]=\sum\limits_{k=i}^{p_{mp}}\sum\limits_{l=p_{mp}}^jf[i,k-1]*f[k,l]*f[l+1,j]\)

    但是,这样是错误的,因为当\([k,l]=[i,j]\)时,\(f[i,j]\)便无法从子状态转移过来!

    我们考虑拆开\(f[k,l]\)。因为再往后的染色中,位置\(p_{mp}\)一定没有再被染色过,因此有\(f[k,l]=f[k,p_{mp}-1]*f[p_{mp}+1,l]\)

    \(f[i,j]=\sum\limits_{k=i}^{p_{mp}}\sum\limits_{l=p_{mp}}^jf[i,k-1]*f[k,p_{mp}-1]*f[p_{mp}+1,l]*f[l+1,j]\)

    特殊定义一下,对于\(f[i,j]\),如果\(i>j\),则\(f[i,j]=1\)。这也是为了转移的正确(在应用上述式子时可能会调用到这样的\(f[i,j]\)

    上面的转移是\(O(n^4)\)的;但当我们拆开两个\(\sum\),就可以把它化成\(O(n^3)\)的。

    \(f[i,j]=(\sum\limits_{k=i}^{p_{mp}}f[i,k-1]*f[k,p_{mp}-1])*(\sum\limits_{l=p_{mp}}^jf[p_{mp}+1,l]*f[l+1,j])\)

    前后两个括号内的内容互不干涉,故可以分开计算。

    复杂度\(O(n^3)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=998244353;
    int n,num[510],f[510][510];
    int main(){
    	scanf("%d%d",&n,&n);
    	for(int i=1;i<=n;i++)scanf("%d",&num[i]);
    	for(int i=1;i<=n+1;i++)for(int j=0;j<i;j++)f[i][j]=1;
    	for(int i=1;i<=n;i++)f[i][i]=1;
    	for(int l=2;l<=n;l++)for(int i=1,j=i+l-1;j<=n;i++,j++){
    		int mp=i;
    		for(int k=i;k<=j;k++)if(num[k]<=num[mp])mp=k;
    		int A=0,B=0;
    		for(int k=mp;k>=i;k--)(A+=(1ll*f[i][k-1]*f[k][mp-1]%mod))%=mod;
    		for(int l=mp;l<=j;l++)(B+=(1ll*f[mp+1][l]*f[l+1][j]%mod))%=mod;
    		f[i][j]=1ll*A*B%mod;
    	}
    	printf("%d\n",f[1][n]);
    	return 0;
    } 
    

  • 相关阅读:
    linux命令行
    mybatis中#{}和${}的区别
    @InitBinder的作用
    mui 实用封装销毁页面
    【SQLite】简单的基本使用步骤
    常用的一些操作方法
    【HttpWeb】Post和GET请求基本封装
    【接口验证】特性验证参数
    小谈单例模式
    vs下开端口直接调试iis
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597323.html
Copyright © 2011-2022 走看看