老曹的忧郁
题目大意
给你一个 n 行的图,第 i 行有 n 个数,所有数放在一起形成了一个等边三角形。
然后问你有多少个数,满足它出现的位置中可以选出三个,它们为顶点形成的三角形是等边三角形。
思路
我们考虑枚举每个等边三角形,然后判断顶点颜色。
然后我们考虑如何统计到所有的等边三角形。
你会发现,这样同一个颜色的组成的三角形都是等边三角形。
这有什么特点呢?
一开始三个粉色的很好确定,那剩下的呢?
红色的可以由粉色顺时针移动一下得到,再移动一些就是橙色,然后是黄色。。。
考虑用这个方法来统计,那首先要枚举这个三角形的位置(我这里枚举的是上面粉色的位置),接着就是枚举这个三角形的大小,然后再一位一位移。
那怎么确定三个的位置呢?
我们考虑让
(
i
,
j
)
(i,j)
(i,j) 为第
i
i
i 行第
j
j
j 个。
然后我们想一想,我们假设上面的粉色是
(
x
,
y
)
(x,y)
(x,y),三角形大小是
l
l
l,那左边右边的粉色就分别是:
(
x
+
l
−
1
,
y
)
,
(
x
+
l
−
1
,
y
+
l
−
1
)
(x+l-1,y),(x+l-1,y+l-1)
(x+l−1,y),(x+l−1,y+l−1)。
然后假设顺时针动了
p
p
p 次,三个的位置就变成了
(
x
+
p
−
1
,
y
)
,
(
x
+
l
−
1
,
y
+
p
−
1
)
,
(
x
+
l
−
1
−
p
+
1
,
y
+
l
−
1
−
p
+
1
)
(x+p-1,y),(x+l-1,y+p-1),(x+l-1-p+1,y+l-1-p+1)
(x+p−1,y),(x+l−1,y+p−1),(x+l−1−p+1,y+l−1−p+1)。
然后就可以啦。
代码
#include<cstdio>
using namespace std;
int n, m, pp[101][101];
char c[101];
bool yes[31], no;
struct pl {
int x, y;
}a[101], ii, jj, kk;
pl get_pl(int now) {
pl re;
re.x = 1; re.y = 0;
while (now > re.x) {
now -= re.x;
re.x++;
}
re.y = now;
return re;
}
int main() {
scanf("%d", &n);
m = n * (n + 1) / 2;
scanf("%s", c + 1);
for (int i = 1; i <= m; i++) a[i] = get_pl(i), pp[a[i].x][a[i].y] = i;
no = 1;
for (int i = 1; i <= m; i++) {//枚举大三角上面的顶点
for (int l = 2; a[i].x + l - 1 <= n; l++) {//枚举大三角的大小
for (int p = 1; p < l; p++) {//枚举转的大小
int x = pp[a[i].x + p - 1][a[i].y];//得到三个点
int y = pp[a[i].x + l - 1][a[i].y + p - 1];
int z = pp[a[i].x + l - 1 - p + 1][a[i].y + l - 1 - p + 1];
if (c[x] == c[y] && c[y] == c[z]) {//判断是否颜色相同
no = 0;
yes[c[x] - 'a'] = 1;
}
}
}
}
if (no) printf("Harmonious");
else {
for (int i = 0; i < 26; i++)
if (yes[i]) putchar(i + 'a');
}
return 0;
}