题意
求有多少 (n imes n) 的 01 矩阵,满足:
- 任意相邻两行或两列,要么完全相同,要么完全相反;
- 不存在面积大于等于 (k) 的、全是 (0) 或全是 (1) 的矩形。
(nleq 500)
题解
观察可得第一个要求相当于将整个矩形横着切若干刀,竖着切若干刀,并交错着填 0、1。DP 出把长为 (j) 的一段切成长度不超过 (i) 的若干段的方案数。枚举横着的两刀之间的最长间隔,确定竖着的最长间隔应当小于等于某个数。前缀和优化 DP 可以做到 (O(n^2))。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=510,mod=998244353;
int f[N][N],s[N][N];
int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
f[i][0]=1;
s[i][0]=1;
for(int j=1;j<=n;j++){
f[i][j]=s[i][j-1]-(j-i-1>=0?s[i][j-i-1]:0);
f[i][j]<0&&(f[i][j]+=mod);
s[i][j]=s[i][j-1]+f[i][j];
s[i][j]>=mod&&(s[i][j]-=mod);
}
}
int ans=0;
for(int i=1;i<=n;i++){
int j=(k-1)/i;
j=min(j,n);
ans=(ans+(f[i][n]-f[i-1][n]+mod)*1ll*f[j][n]%mod)%mod;
}
cout<<ans*2%mod;
}