b352: 相似
Tags: math
出處:https://zerojudge.tw/ShowProblem?problemid=b352
提交:https://zerojudge.tw/Submissions?problemid=b352&account=allllllan123456
問題:給你 $n\in[1,100000]$ 組三根棍子的長度 $\in\text{int}^+$,先問你這其中有幾組棍子可以自己組成一個 (面積為正的) 三角形,接著再繼續把彼此相似的三角形們合成一類,問你最大類的三角形個數少一是多少。
解法:首先,要判斷一組三角形邊長是否合法,必須先把棍子長由小到大排序,而且檢查兩小邊之和大於第三邊的時候必須轉成減法操作以免溢位。另外,對於每個三角形其實都存在唯一一個三邊長 $a,b,c$ 滿足 $a\le b\le c$ 且 $\gcd(a,b,c)=1$ 的三角形與之相似,我稱滿足上述條件的三角形為「最簡三角形」,事實上兩個三角形「相似」若且為若 (if and only if) 它們各自對應的最簡三角形「全等」,因此我只要想辦法把每個三角形都化成它們各自對應的最簡三角形,並且加以排序以確保彼此全等的三角形會相鄰,這樣就能知道最大類的相似三角形個數有多少了 (最後記得減一)。
1#include <bits/stdc++.h>
2using namespace std;
3
4int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); // IO 優化
5 vector<tuple<int, int, int>> v; int n; cin >> n;
6 while (n--) { int a[3];
7 cin >> a[0] >> a[1] >> a[2];
8 sort(a, a+3);
9 if (a[0] > a[2] - a[1]) { // avoid overflow
10 int d = __gcd(__gcd(a[0], a[1]), a[2]);
11 a[0] /= d; a[1] /= d; a[2] /= d;
12 v.push_back(tuple<int, int, int>(a[0], a[1], a[2]));
13 }
14 }
15 sort(v.begin(), v.end()); // for grouping the similar triangles together
16 int max=0, count=0; tuple<int, int, int> before;
17 for (const auto &e: v)
18 if (e == before) {
19 count++;
20 if (count > max) max = count;
21 } else
22 before = e, count = 0;
23 cout << v.size() << ' ' << max << '\n';
24 return 0;
25}