专栏文章
题解:P11752 [COCI 2024/2025 #5] 挂画 / Zid
P11752题解参与者 5已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @miq5a4un
- 此快照首次捕获于
- 2025/12/03 23:11 3 个月前
- 此快照最后确认于
- 2025/12/03 23:11 3 个月前
看到这题的第一想法是用前缀和。用数组 记录 左上方的钉子数量之和,先抽象出以下图形:


以 代表矩形 中的钉子数量。那么,在图中,如果需要求 ,易知:
那么我们在上式中间两项分别加上 ,得:
译为中文,就是:左上角为 右下角为 的矩形中,有 个钉子。
然后就这么做了,于是 38分 。
发现超时的那个测试点全部是没钉子,回到样例 #1 后,发现只要钉子数不超过 1 ,那么挂的画在任何位置都可以。
显然,每行 个中有 排列组合方式,每一列同理。
故一共有 种排列组合方式
遂 AC 。
代码如下
CPP#include <bits/stdc++.h>
#define ll long long
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
ll n,m,ans;
string s;
ll a[514][514];//存的是左上的钉子数
//思路是前缀和,但是这题用的二维
int main(){
ios;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>s;
for(int j=1;j<=m;j++){
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
if(s[j-1]=='#')a[i][j]++;
}
}
if(a[n][m]<=1){
cout<<n*m*(n+1)*(m+1)/4;
return 0;
}
int f;
for(int i1=1;i1<=n;i1++){
for(int j1=1;j1<=m;j1++){
for(int i2=i1;i2<=n;i2++){
for(int j2=j1;j2<=m;j2++){
f=a[i2][j2]-a[i1-1][j2]-a[i2][j1-1]+a[i1-1][j1-1];
if(f<=1)ans++;
if(f>1)break;
}
}
}
}
cout<<ans;
return 0;
}
感谢阅读。
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...