题目网址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;
}