CF-1027E Inverse Coloring
CF-1027E Inverse Coloring
时间限制:\(2000ms\) 空间限制:\(256MB\)
题目描述:
给定 \(n,k\),试求出有多少 \(n\times n\) 的 01 矩阵,满足:
- 
对于任意相邻两行 \(i,i+1\),所有的 \(j\in [1,n]\) 都满足 \(a_{i,j}=a_{i+1,j}\); 或对于任意相邻两行 \(i,i+1\),所有的 \(j\in [1,n]\) 都满足 \(a_{i,j}\neq a_{i+1,j}\)。 
- 
对于任意相邻两列 \(j,j+1\),所有的 \(i\in [1,n]\) 都满足 \(a_{i,j}=a_{i,j+1}\); 或对于任意相邻两行 \(i,i+1\),所有的 \(j\in [1,n]\) 都满足 \(a_{i,j}\neq a_{i,j+1}\)。 
- 
矩阵内不存在大小超过 \(k\) 个单位的矩阵,使矩阵内每个格子均相等。 
输出对 \(998244353\) 取模的结果。
输入描述:
一行包含两个整数 \(n\) 和 \(k\) (\(1 \le n \le 500\), \(1 \le k \le n^2\)) 。
输出描述:
输出一个整数,对 \(998244353\) 取模。
样例输入输出:
| 输入1 | 输出1 | 输入2 | 输出2 | 输入3 | 输出3 | 
|---|---|---|---|---|---|
| 1 1 | 0 | 2 3 | 6 | 49 1808 | 359087121 | 
样例解释:
以下是样例二满足条件的染色方式:

思路
观察可得,当第一行第一列确定下来后,整个矩阵也就确定下来了。最终矩阵内颜色相同的最大子矩阵的长与宽分别是第一行、第一列内最长连续相同子段。
而第一行第一列本质是相同的,可以一起处理。
所以现在问题转化为:求长度为 \(n\) 的 01 串,满足其内部最长连续相同字串的长度等于 \(j\)。
考虑 dp,令 \(f_{i,j}\) 表示对于前 \(i\) 个位置,最长连续相同字串的长度为 \(j\) 的方案数。
转移分为两种情况:
- 在上一个串后直接添加 \(j\) 个元素,方案数为 \(\sum_{k=0}^{j} f_{i-j,k}\);
- 在上一个满足最长连续相同字串长度为 \(j\) 的字串后添加一段长度小于 \(j\) 的元素,方案数为 \(\sum_{k=1}^{j-1}f_{i-k,j}\)。
最终答案即为 \(\dfrac{\sum [i\times j<k]\times f_{n,i}\times f_{n,j}}{2}\).
除以二是因为需要满足列的第一项与行的第一项相同。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int n,k,ans;
int dp[510][510];
void Mod(int &x)
{
	if(x<=0) x+=mod;
	if(x>=mod) x-=mod;
	if(x>=mod) x%=mod;
}
int ksm(int a,int b)
{
	if(b==0) return 1;
	int re=ksm(a,b>>1);
	re=re*re%mod;
	if(b&1) re=re*a%mod;
	return re;
}
signed main()
{
	cin>>n>>k;
	dp[0][0]=2;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=i;j++)
		{
			for(int k=0;k<=j;k++) dp[i][j]+=dp[i-j][k],Mod(dp[i][j]);
			for(int k=1;k<j;k++) dp[i][j]+=dp[i-k][j],Mod(dp[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i*j>=k) break;
			ans+=dp[n][i]*dp[n][j]%mod*ksm(2,mod-2)%mod;
			Mod(ans);
		}
	}
	cout<<ans<<endl;
	return 0;
} 
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号