본문으로 건너뛰기
김신건의 로그

피타고라스 정리 (Pythagorean Theorem)

· 수정 · 📖 약 2분 · 671자/단어 #algorithm #geometry #pythagoras
pythagorean theorem, 피타고라스 정리, 피타고라스 수, pythagoras, pythagorean triple

정의

피타고라스 정리는 직각삼각형에서 빗변 c 의 제곱이 두 직각변 a, b 의 제곱의 합과 같다는 정리: c^2 = a^2 + b^2. 기원전 6세기 그리스 수학자 피타고라스가 증명. 피타고라스 수 (Pythagorean triple) 는 이 등식을 만족하는 세 자연수 (a, b, c) 쌍으로 (3, 4, 5) 가 가장 잘 알려짐.

문제 상황과 동기

2D 평면에서 두 점 사이의 거리, 직각 판별, 원의 방정식 등 기하의 거의 모든 곳에서 피타고라스 정리가 쓰임.

  • Naive 접근: 세 변이 주어졌을 때 a^2 + b^2 = c^2 를 확인하려면 세 변을 정렬한 후 O(1).
  • 핵심 통찰: c 가 항상 가장 크므로 정렬 후 한 번의 검사로 직각 판별 가능.
  • PS 위치: 두 점 거리의 제곱을 그대로 비교해 실수 연산 회피. 좌표 기하 문제의 가장 기초.

시각화

핵심 아이디어

c^2 = a^2 + b^2

직각삼각형:
- a, b: 직각변 (legs)
- c: 빗변 (hypotenuse), 항상 가장 긴 변

Euclid 공식 (primitive triple 생성):
a = m^2 - n^2
b = 2mn
c = m^2 + n^2
조건: m > n, gcd(m,n)=1, m-n 은 홀수

알고리즘

is_right_triangle(a, b, c):
    sides = [a, b, c] 정렬
    return sides[0]^2 + sides[1]^2 == sides[2]^2

generate_triples(limit):
    for m = 2..sqrt(limit):
        for n = 1..m-1:
            if (m-n) is even: continue
            if gcd(m, n) != 1: continue
            a = m^2 - n^2, b = 2mn, c = m^2 + n^2
            if c > limit: continue
            for k = 1; k*c <= limit; k++:
                output (k*a, k*b, k*c)

구현

// 피타고라스 수 생성 + 직각 판별
#include <bits/stdc++.h>
using namespace std;
int main() {
  int limit; cin >> limit;
  vector<tuple<int,int,int>> triples;
  for (int m = 2; m*m <= limit; m++) {
      for (int n = 1; n < m; n++) {
          if ((m-n) % 2 == 0) continue;
          if (gcd(m, n) != 1) continue;
          int a = m*m - n*n, b = 2*m*n, c = m*m + n*n;
          if (c > limit) continue;
          for (int k = 1; k*c <= limit; k++)
              triples.push_back({k*a, k*b, k*c});
      }
  }
  cout << "Found " << triples.size() << " triples:\n";
  for (auto& [a,b,c] : triples)
      cout << a << " " << b << " " << c << "\n";
  int x, y, z; cin >> x >> y >> z;
  vector<int> v = {x, y, z};
  sort(v.begin(), v.end());
  bool right = v[0]*v[0] + v[1]*v[1] == v[2]*v[2];
  cout << (right ? "RIGHT" : "NOT RIGHT") << "\n";
}
stdin
50
3 4 5
결과
Found 5 triples
3 4 5
5 12 13
8 15 17
7 24 25
20 21 29
RIGHT

복잡도

항목
직각 판별 (3 변)O(1)
Triple 생성 (limit L)O(L log L)
Triple 생성 공간O(L)

변형 / 활용

응용설명
유클리드 거리sqrt((x1-x2)^2 + (y1-y2)^2)
제곱 거리 비교sqrt 없이 제곱 상태로 비교 (실수 오차 회피)
내적과 직각두 벡터의 내적이 0 이면 직각. 좌표 기하에서 활용

함정

1. 빗변 식별 실수

가장 큰 변을 빗변으로 지정해야 함. 정렬 없이 a^2 + b^2 == c^2 만 검사하면 c 가 빗변이 아닐 때 오답.

2. 오버플로우

N=10^5 에서 좌표 제곱은 10^10 -> 32-bit int 초과. 반드시 long long 사용.

3. 실수 sqrt 비교

sqrt(a^2 + b^2) == c 는 부동소수점 오차 유발. 반드시 정수 제곱으로 비교.

BOJ 연습 문제

번호제목정답률링크
BOJ 4153직각삼각형-kokoa-lab
BOJ 3000직각삼각형-kokoa-lab
BOJ 1711직각삼각형-kokoa-lab
BOJ 1485정사각형-kokoa-lab

참고

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기