【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);
}

posted @ 2023-02-05 09:47  Syara  阅读(27)  评论(1编辑  收藏  举报