SangYoonLee (SYL)
◆ Slow, But Steady ◆
SangYoonLee (SYL)
전체 방문자
오늘
어제
  • ◻ 전체 글 수 : (128)
    • ✪ 취미, 경험 회고 및 일상 (25)
      • [취미] Room Escape (2)
      • [회고] IT 관련 경험 회고 (17)
      • [일상] 일상 생각 (4)
      • [일상] 독후감 (1)
    • ◼ FrontEnd (27)
      • Web & HTML, CSS (8)
      • JavaScript (2)
      • TypeScript (1)
      • ReactJS (16)
    • ◼ CS (3)
      • 자료구조 & 알고리즘 (1)
      • 컴퓨터 구조 (1)
      • 운영체제 (1)
    • ◼ PS Note (40)
      • 백준 (38)
      • 프로그래머스 (2)
    • ◼ IT Etc. (33)
      • (Until 2021) (21)
      • Python (6)
      • C | C# | C++ (1)
      • Git (1)
      • Unity (4)
      • Game Dev. (0)

블로그 메뉴

  • 홈
  • 💻 GitHub
  • 🟢 Velog
  • 🧩 온라인 방탈출 출시 작품 모음

인기 글

최근 글

공지사항

반응형
hELLO · Designed By 정상우.
SangYoonLee (SYL)

◆ Slow, But Steady ◆

◼ IT Etc./(Until 2021)

[알고리즘] 최대공약수와 최소공배수 - 간단하게 구현해보기 (+ 유클리드 호제법 알고리즘) (C++)

2021. 4. 9. 17:20
반응형

 

<1> 최대공약수란 무엇인가?

 

최대공약수는 초등학교 수학 시간에 배우는 내용으로, 아마 이 글을 보시는 여러분이라면 이미 아시겠지만, 그 개념을 한 번 더 짚고 넘어가보자.

 

쉬운 이해를 위해 실제 정의가 아닌 초등학교 교과서에 제시된 내용을 참고하였다.

 

 

n의 약수 : n을 나누어 떨어지게 하는 수

 

a, b의 공약수 : a와 b의 공통된 약수

 

a, b의 최대공약수 : a와 b의 공통된 약수 중 가장 큰 수

 

 

 

이 개념을 이용하여 반복문으로 다음과 같이 최대공약수를 구하는 함수 코드를 쓸 수 있다.

#include <iostream>
#include <algorithm>

// 최대공약수를 계산하는 함수 
long getBCD (long a, long b)
{
	for(int div = min(a, b); div > 0; div--)
    {
    	if((a % div == 0) && (b % div == 0))
        // div : 공약수
        // 최초의 공약수 -> 최대공약수
        	return div;
    }
}

 

이 알고리즘을 개선해, 더 간단한 복잡도로 최대공약수를 구하는 코드가 있다.

 

최대공약수를 구하는 다른 방법으로 '유클리드 호제법 알고리즘'에 대해 알아보자.

 

아마 전공자라면, 학과 수업에서 한 번은 다뤄봤을 내용일 것이다.

 

 


 

<2> 유클리드 호제법 알고리즘

 

'유클리드 호제법 알고리즘'은 '유클리드 호제법'을 통해 최대공약수를 구하는 알고리즘으로

 

인류 최초의 알고리즘이라고 한다. (그렇구나)

 

그 내용은 다음과 같다.

 

 

2개의 자연수(또는 정식) A, B에 대해서 A를 B로 나눈 나머지를 R이라 하면 (단, A > B)

 

A와 B의 최대공약수는 B와 R의 최대공약수와 같다. (유클리드 호제법)

 

 

(수식으로 증명)

 

A = BQ + R  ->  gcd(A, B) = G이면,

 

A = Ga, B = Gb (a, b는 서로소)

 

Ga = GbQ + R

 

R = G(a - bQ)

 

gcd(B, R) = G

 

 

 

 

이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여

 

나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다. (유클리드 호제법 알고리즘)

 

 

(수식으로 설명)

 

A = B(Q1) + (R1),  gcd(A, B) = G

 

B = R1(Q2) + (R2), gcd(B, R1) = G

 

R1 = R2(Q3) + (R3), gcd(R1, R2) = G

 

...

 

R(n-1) = Rn(Q(n+1)), gcd(R(n-1), Rn) = G

 

 

gcd(A, B) = gcd(B, R1) = ... = gcd(R(n-1), Rn) = G

​

 

 

 

 

두 정수 A, B에 대하여

 

A의 약수가 B라면 ( A = BQ ), A와 B의 최대공약수는 B가 된다.

 

그렇지 않다면 ( A = BQ + R (R!=0) ), 'A와 B의 최대 공약수' == 'B와 (A%B)의 최대공약수' 이다.

 

 

즉, (A % B) != 0 이라면 gcd(A, B) == gcd (B, A%B)이고

 

(A % B) == 0 이면, gcd(A, B) == B인것이다.

 

 

이 알고리즘을 이용해 최대공약수를 구하는 코드를 작성하면 다음과 같다.

 

long getGCD(long a, long b)
{
	long temp = a % b;
	
	while (temp != 0)
	{
		a = b;
		b = temp;
		temp = a % b;
	}
	
	return b;
}

이 알고리즘의 핵심은, (A % B) != 0 일 때 gcd(A, B) == gcd(B, A%B)임을 이용해

 

(A % B)값이 0이 될 때까지 나머지를 계산하는 과정을 반복하는 것이다.

 

참고로 A < B일 때도 이 알고리즘은 성립한다.

 


 

<3> 최소공배수 구현

 

두 정수 A, B의 최소공배수는 'A의 배수이면서 동시에 B의 배수가 되는 최소의 수'이다.

 

역시 반복문으로 다음과 같이 최소공배수를 구하는 함수 코드를 쓸 수 있다.

 

#include <iostream>
#include <algorithm>

// 최소공배수를 계산하는 함수 
long getLCM (long a, long b)
{
	for(int mul = max(a, b); mul <= a * b; mul++)
    {
    	if((mul % a == 0) && (mul % b == 0))
        // mul : 공배수
        // 최초의 공배수 -> 최소공배수
        	return mul;
    }
}

만일 A, B의 최대공약수를 안다면, 이 알고리즘 역시 더 간단한 복잡도 개선할 수 있다.

 

최소공배수에는 다음과 같은 성질이 있다.

 

 

lcm(A, B) = AB / gcd(A, B)

 

 

(간단한 증명)

 

위 최대공약수에서 이용한 수식을 재탕하자.

 

A = BQ + R

 

gcd(A, B) = G,  A = Ga, B = Gb (a, b는 서로소)

 

이 때, lcm(A, B) = Gab

 

즉, Gab = AB / G

 

Gab = (Ga)(Gb) / G

 

Gab = Gab

 

 

 

 

A, B의 최대공약수 값과 이 성질을 이용해 코드를 개선해보자.

// 최대공약수 구하는 함수
long getGCD(long a, long b)
{
	long temp = a % b;
	
	while (temp != 0)
	{
		a = b;
		b = temp;
		temp = a % b;
	}
	
	return b;
}


// 최소공배수 구하는 함수
long long getLCM(long long a, long long b)
{
	return a * b / getGCD(a, b);
}

반복문을 쓸 필요도 없이 딱 한 줄의 함수로 구할 수 있다.

 

반응형

'◼ IT Etc. > (Until 2021)' 카테고리의 다른 글

[파이썬] 기억력 테스트 게임 제작 보면서 따라 만들기 (pygame) - 완성 및 후기  (0) 2021.04.19
[파이썬] 오락실 게임 제작 보면서 따라 만들기 (pygame) - (1) 기본 과정 (예제 연습, 기본 틀)  (0) 2021.04.10
눈 수술로 인해 잠시 공백기가 있었습니다.  (0) 2021.04.07
[C++] 클래스의 private 접근 제어자의 지정 범위  (0) 2021.03.28
제대 후 첫 슬럼프, 극복을 위한 공부의 변화  (0) 2021.03.23
    '◼ IT Etc./(Until 2021)' 카테고리의 다른 글
    • [파이썬] 기억력 테스트 게임 제작 보면서 따라 만들기 (pygame) - 완성 및 후기
    • [파이썬] 오락실 게임 제작 보면서 따라 만들기 (pygame) - (1) 기본 과정 (예제 연습, 기본 틀)
    • 눈 수술로 인해 잠시 공백기가 있었습니다.
    • [C++] 클래스의 private 접근 제어자의 지정 범위
    SangYoonLee (SYL)
    SangYoonLee (SYL)
    Slow, But Steady Wins The Race 😎

    티스토리툴바