Codeforces 1027E Inverse Coloring【DP】

题目链接

E. Inverse Coloring

You are given a square board, consisting of nn rows and nn columns. Each tile in it should be colored either white or black.

Let's call some coloring beautiful if each pair of adjacent rows are either the same or different in every position. The same condition should be held for the columns as well.

Let's call some coloring suitable if it is beautiful and there is no rectangle of the single color, consisting of at least kk tiles.

Your task is to count the number of suitable colorings of the board of the given size.

Since the answer can be very large, print it modulo 998244353998244353.

Input

A single line contains two integers nn and kk (1≤n≤5001≤n≤500, 1≤k≤n21≤k≤n2) — the number of rows and columns of the board and the maximum number of tiles inside the rectangle of the single color, respectively.

Output

Print a single integer — the number of suitable colorings of the board of the given size modulo 998244353998244353.

Examples

input

Copy

1 1

output

Copy

0

input

Copy

2 3

output

Copy

6

input

Copy

49 1808

output

Copy

359087121

Note

Board of size 1×11×1 is either a single black tile or a single white tile. Both of them include a rectangle of a single color, consisting of 11 tile.

Here are the beautiful colorings of a board of size 2×22×2 that don't include rectangles of a single color, consisting of at least 33 tiles:

The rest of beautiful colorings of a board of size 2×22×2 are the following:

题意:给一个n*n的矩阵染色,每个方格只能被然后黑色和白色。要求要满足任意两行或任意两列的颜色要完全相同或者完全不同。矩形内部不能存在一个面积大于k的由一种颜色组成的小矩形。

题解:首先我们假设每行有个系数a_i,每列有一个系数b_j则第i行第j列的颜色为a_i xor b_j。就可以巧妙的解决第一个要求。假设求出长度n的01串的最长连续0或1的个数为x设为d[x],那个当行最长连续与列最长连续的积小于k就可以满足要求。对于长度为n的最长连续长度为x的01串可以用差分求出来,设c[x]为长度最长连续长度小于等于x的个数,则d[x]=c[x]-c[x-1]。c[x]可以用dp维护。

设dp[i][j]为长度为i的最长连续小于j的个数,则转移方程为: dp[i][j]=\sum_{k=1}^{min(i,j)}dp[i-k][j]

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD=998244353;
LL dp[505][505],a[505];
int main()
{
    int n,k;printf("%.5f\n",(double)clock()/CLOCKS_PER_SEC);
    scanf("%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(i,j); k++)
                dp[i][j]=(dp[i][j]+dp[i][j-k])%MOD;
    }
    for(int i=1; i<=n; i++)
        a[i]=(dp[i][n]-dp[i-1][n]+MOD)%MOD;
    LL ans=0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            if(i*j<k)
                ans+=a[i]*a[j]%MOD;
    ans=ans*2%MOD;
    printf("%lld\n",ans);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值