【题解】[Codeforces 1027E] Inverse Coloring【计数DP 前缀和优化】

题目链接

题意

求有多少 \(n\times n\) 的 01 矩阵,满足:

  • 任意相邻两行或两列,要么完全相同,要么完全相反;
  • 不存在面积大于等于 \(k\) 的、全是 \(0\) 或全是 \(1\) 的矩形。

\(n\leq 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;
}

posted @ 2020-11-26 18:31  破壁人五号  阅读(74)  评论(0编辑  收藏  举报