【CF52B】Right Triangles
update on 2022.04.26:
修改了一处炸掉的格式。
一、题意
题目给我们一个 \(n\times m\) 的字符矩阵,求三个*
为顶点且直角边水平或竖直的三角形。
二、思路
首先想到的显然是暴力:
\(\text{找到一个点->找到另一个点->判断是否符合条件}\)
显然,不明确计算复杂度也知道肯定上天了。
那怎么办呢?
我们仔细观察这样一个图形:
......
....*.
....*.
......
....*.
*..***
你可以数一下,其中有\(3\times3=9\)个三角形。
于是,我们会发现:
设 \(col_i\) 表示第 \(i\) 列 *
的个数, \(row_i\) 表示第 \(i\) 行 *
的个数。
则以第 \(i\) 行,第 \(j\) 列这个 *
为顶点的三角形有 \(\left(col_i-1\right)\times\left(row_i-1\right)\) 个(请您思考为什么要减一)。
此时,标程呼之欲出了。
三、代码
由上面的式子直接写就可以了。
减一的原因是 第 \(i\) 行,第 \(j\) 列这个字符本身也是* 。
#include <stdio.h>
#include <string.h>
using namespace std;
int _x;char _c;
int read(){
_x=0;_c=getchar();
while(_c<'0'||_c>'9')_c=getchar();
while(_c<='9'&&_c>='0'){
_x=(_x<<1)+(_x<<3)+(_c^'0');
_c=getchar();
}
return(_x);
}//加速读入
int n,m;
char c;char s[1005][1005];
int col[1005],row[1005];
int main(){
freopen("triangle.in","r",stdin);
freopen("triangle.out","w",stdout);
long long ans=0;//注意 long long
n=read();m=read();
for(int i=1;i<=n;getchar(),i++)//getchar()似乎比cin.get(),scanf都要快,但是比fread慢
for(int j=1;j<=m;j++){
s[i][j]=c=getchar();
if(c=='*')++row[i],++col[j];
}//读入矩阵存入s,并算出row,col数组。
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='*')//这个if不能少
ans+=(row[i]-1)*(col[j]-1);
printf("%lld\n",ans);//输出
return(0);
}