题解:「NOIP2022 提高组」种花
题解:「NOIP2022 提高组」种花
题目大意:给定一个
原题面中对形状的定义是这样的:
一种种花方案被称为
形的,如果存在 ,以及 ,满足 ,并且 ,使得第 行的第 到第 列、第 行的第 到第 列以及第 列的第 到第 行都不为土坑,且只在上述这些位置上种花。 一种种花方案被称为
形的,如果存在 ,以及 ,满足 ,并且 ,使得第 行的第 到第 列、第 行的第 到第 列以及第 列的第 到第 行都不为土坑,且只在上述这些位置上种花。
先考虑C形,发现当两横线位置固定时,竖线位置是固定的。所以只需关心横线对答案的贡献
横线对答案的贡献等于两横线长度之积,怎么快速求出每个点往右能延伸的最大长度呢?每一行从右往左做后缀和即可,预处理可以在
考虑
第一层循环枚举列数
第二层枚举上方横线所在行号
第三层枚举下方横线所在行号
记
那F形呢?发现就是在C的基础上在竖线下方加一截。
记
时间复杂度
正解:
考虑怎么优化到
发现固定
所以记
注意做的也是后缀和而不是前缀
然后就只需要枚举
#include<bits/stdc++.h>
#define F(i,l,r) for(int i=l;i<=r;++i)
#define G(i,r,l) for(int i=r;i>=l;--i)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
const int N=1010;
const ll mod=998244353;
int n,m,vc,vf,t,id;
char ch[N][N];
ll ansf,ansc,r[N][N],c[N][N],sr[N][N],ssr[N][N];
int main(){
// freopen("plant.in","r",stdin);
// freopen("plant.out","w",stdout);
scanf("%d%d",&t,&id);
while(t--){
ansf=0,ansc=0,mem(r),mem(c),mem(sr),mem(ssr),mem(ch);
scanf("%d%d%d%d",&n,&m,&vc,&vf);
F(i,1,n) scanf("%s",ch[i]+1);
if(!vc && !vf){ puts("0 0"); continue; }
F(i,1,n) G(j,m,1) ch[i][j]=='1'?r[i][j]=0:r[i][j]=r[i][j+1]+1;
F(j,1,m) G(i,n,1) ch[i][j]=='1'?c[i][j]=0:c[i][j]=c[i+1][j]+1;
F(j,1,m) G(i,n,1) {
if(ch[i][j]=='1') continue;
sr[i][j]=r[i][j]-1,ssr[i][j]=(r[i][j]-1)*(c[i][j]-1)%mod;
if(ch[i+1][j]=='0' && i+1<=n) sr[i][j]=(sr[i][j]+sr[i+1][j])%mod,ssr[i][j]=(ssr[i][j]+ssr[i+1][j])%mod;
}
F(j,1,m){
F(i,1,n-2){
if(r[i][j]<=1 || ch[i+1][j]=='1' || ch[i+2][j]=='1') continue;
ansc=(ansc+(r[i][j]-1)*sr[i+2][j]%mod)%mod;
ansf=(ansf+(r[i][j]-1)*ssr[i+2][j]%mod)%mod;
}
}
printf("%lld %lld\n",vc?ansc:0,vf?ansf:0);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】