CF Educational Codeforces Round 49 E. Inverse Coloring
? 解题记录 ? ? Codeforces ? ? 动态规划 ?    2018-09-16 16:14:11    480    0    0

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 (1n5001≤n≤5001kn21≤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

## 然后我们考虑纯色矩形大小的限制，可以先处理出f(i)表示最长有i个连续格子的列有多少种，这个可以O(n^3) dp得到，然后我们再横着摆放这些列，因为要满足限制，所以假如当前放的列上最大的矩形为i，不能连续n/i列都不反色。最后总复杂度O(n^3)。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define For(i, a, b) for(register int i = a; i <= b; ++i)
using namespace std;
const int mod = 998244353;
const int maxn = 5e2 + 5;

int now, n, Mx;
int dp[2][maxn][maxn];
int g[maxn];

void Add(int & a, const int &b) {
a += b;
if(a > mod) a -= mod;
}

int main() {
scanf("%d%d", &n, &Mx);
dp[now][1][1] = 2;
For(i, 1, n - 1) {
memset(dp[now ^ 1], 0, sizeof(dp[now ^ 1]));
For(j, 1, i + 1) For(k, 1, i + 1) {
Add(dp[now ^ 1][j + 1][max(j + 1, k)], dp[now][j][k]);
Add(dp[now ^ 1][1][k], dp[now][j][k]);
}
now ^= 1;
}
For(j, 1, n) For(k, 1, n)
memset(dp, 0, sizeof(dp)), now = 0;
For(i, 1, n) if(i < Mx) dp[now][1][i] = g[i];
For(i, 1, n - 1) {
memset(dp[now ^ 1], 0, sizeof(dp[now ^ 1]));
For(j, 1, i + 1)
For(k, 1, n) {
//cout << i << " " << j << " " << k << " " << dp[now][j][k] << endl;
if((j + 1) * k < Mx) {
Add(dp[now ^ 1][j + 1][k], dp[now][j][k]);
//cout << i << " " << j << " " << k << "-" << dp[now][j][k] << ">" << i + 1 << " " << j + 1 << " " << k << endl;
}
//cout << i << " " << j << " " << k << "-" << dp[now][j][k] << ">" << i + 1 << " " << 1 << " " << k << endl;
Add(dp[now ^ 1][1][k], dp[now][j][k]);
}
now ^= 1;
}
int ans = 0;
For(j, 1, n)
For(k, 1, n)
}