【DP】Codeforces1027E Inverse Coloring

题意:

给出一个n*n的矩阵,要求在每个位置涂上黑/白色,要求满足:任意相邻的两行,其颜色要么完全相同,要么完全相反。任意相邻的两列,其颜色也要么相同要么完全相反。

且这个矩形中,不存在任意一个大小大于等于k的同色矩形。


分析:

很简单的DP水题。。。。

我们可以把这个矩形的的每一行设一个值 a i ,每一列设定一个值 b i 。其中 a i , b i = 0 1

然后对于格子 ( i , j ) 其颜色就是: a i   x o r   b j

可以保证这样一定满足前两个条件。

然后就是要满足第3个条件。

无非就是 a 中最长的一段连续相同的值和 b 中最长的一段连续相同的值的乘积不超过k

就可以用dp求出:对于最长连续相同长度刚好为 x 的,总长度为n的01序列的方案数。

发现这个刚好为x其实不便表示,所以可以用一下差分的思想:求出最长长度不超过x的方案数,设为 d p x ,然后我们要的就是 d p x d p x 1 。这样就排除了所有长度未达到x的方案。

然后这个dp就非常简单了
d p ( i , j ) 表示前i个位置,最长连续相同不超过j的方案数。

然后 d p ( i , j ) = k = 1 , k m i n ( j , i ) d p ( i k , j )

代码28行。。。算是我做过的最简单的E题了。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 510
#define MOD 998244353 
using namespace std;
typedef long long ll;
int n,k;
ll dp[MAXN][MAXN],res,ans[MAXN];
int main(){
    SF("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        dp[i][0]=1;
        for(int j=1;j<=n;j++)
            for(int k=1;k<=min(j,i);k++)
                dp[i][j]=(dp[i][j]+dp[i][j-k])%MOD;
    }
    for(int i=1;i<=n;i++)
        ans[i]=(dp[i][n]-dp[i-1][n]+MOD)%MOD;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(i*j<k)
                res=(res+ans[i]*ans[j])%MOD;
    PF("%I64d",res*2ll%MOD);
} 

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/81835687
今日推荐