标签:ref 完全 tps 链接 yam class int deb bug
题目链接:https://codeforces.com/contest/1027/problem/E
题目大意:
给一个n*n的矩阵(n<=500),要求将其填满,每一个为黑或白,任意两行或两列,要么完全相同,要么完全相反,并且填充的方格内,任意相同颜色矩形的面积不大于k,求填充方案数。
题目分析:
很好的一道题目,不难发现,若确定第一行和第一列,整个图形也就定了,并且构成相同颜色的矩形区域,在第一行和第一列部分颜色必然是相同连续的,例如第一行为黑黑黑白白黑,可以将其划分为长度为3,2,1的三个部分,第一列为黑黑白白黑黑可划分为2,2,2三个部分,则整个图形最大面积为3*3=6。我们只需要计算长度为n时,最大连续区域颜色相同的方案,然后枚举长和宽即可。
用dp[i][j]表示铺到第i个,最长相同的连续段为j的方案数。那么到i,j的方案就有两种,第一种为最后一块的长度为k,即从i-j块直接铺过来,另一种最后一块长度不到k,而之前的最长连续长度为k,则最后一段从i-j开始,到i-1位置。
因此,dp转移方程为$dp[i][j]= \sum_{k=1}^{j}dp[i-j][k]+\sum_{k=i-j}^{i-1}dp[k][j]$。最后最长连续字段长度为i的方案数即为dp[n][i],因为黑白两种颜色,所以最后答案要乘以2即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; typedef pair <int,int> pii; #define rep(i,x,y) for(int i=x;i<y;i++) #define rept(i,x,y) for(int i=x;i<=y;i++) #define per(i,x,y) for(int i=x;i>=y;i--) #define all(x) x.begin(),x.end() #define pb push_back #define fi first #define se second #define mes(a,b) memset(a,b,sizeof a); #define mp make_pair #define dd(x) cout<<#x<<"="<<x<<" " #define de(x) cout<<#x<<"="<<x<<"\n" #define debug() cout<<"I love Miyamizu Mitsuha forever.\n" const int inf=0x3f3f3f3f; const int maxn=505; const int mod=998244353; ll dp[maxn][maxn]; ll len[maxn]; int main() { mes(dp,0); ios::sync_with_stdio(false); cin.tie(0); int n,s; cin>>n>>s; dp[0][1]=1; rept(i,1,n) { rept(j,1,i)//from 1 to i, the max length of contious block is j { rep(k,1,j) dp[i][j]=(dp[i][j]+dp[i-j][k])%mod; rept(k,i-j,i-1) dp[i][j]=(dp[i][j]+dp[k][j])%mod; } } ll ans=0; rept(i,1,n) len[i]=dp[n][i]; rept(i,1,n) { rept(j,1,n) { if(i*j<s) ans+=len[i]*len[j]; ans%=mod; } } cout<<(ans*2)%mod<<"\n"; return 0; }
CF 1027 E.Inverse Coloring(dp)
标签:ref 完全 tps 链接 yam class int deb bug
原文地址:https://www.cnblogs.com/FZUzyz/p/12255690.html