codeforces 1027E - Inverse Coloring(dp)

题目网址http://codeforces.com/problemset/problem/1027/E

题意:

       n*n的格子,被染成白色或者黑色,每一行与其相邻的那一行的颜色要么完全相同,要么完全不同,其列也是如此。在一个n*n的矩阵中,满足条件,其中格子颜色全部相同子矩形的格子数不超过k。

思路:

   因为题目要求的特性,我们发现只要确定一行一列的话,就可以确定整个n*n的矩阵的染色情况。

  我们定义 dp[i][j] 长度为 i 的行,最多有连续长度为 j 的格子数颜色相同的染色方案的数目 。

 那么递推方程很容易得出。

这样我们可以用差分的思想,得出长度为n 的连续长度为j的染色方案数目,为dp[n] [j]  - dp[n][j-1] ;

那么我们通过枚举行列连续染色数目的情况,就可以得到最终答案。 只要行的连续长度a 和列的连续长度 b  a*b<k,那么即是符合要求的答案。 那么应该是两种方案数相乘dp[n] [a]  * dp[n] [b]   。

注意最后得到的答案还要*2 ,因为把黑白两色互换的话,是可以同样的结果。

 代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define  ll long long
using namespace std;
const int maxn = 500+50;
const ll mod = 998244353;
ll dp[maxn][maxn];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    dp[0][0] = 1;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++)
            for(int k=1; k<=j; k++)
            {
                dp[i][j] = (dp[i][j] + dp[i-k][min(j,i-k)])%mod; //因为dp[i][j] 的j<=i,所以需要取min
            }
    for(int i=n; i>=1; i--)
        dp[n][i] = (dp[n][i] - dp[n][i-1] + mod )%mod;
    ll ans = 0;
    for(int i=1; i<=n; i++)
        for(int j=1; j*i<k && j<=n; j++)
        {
            ans= (ans + dp[n][i]*dp[n][j]%mod) %mod;
        }
    ans = (ans*2)%mod;//黑白两色互换
    printf("%lld\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值