14490 백대열

KimDaeHyun·2024년 8월 18일

백준

목록 보기
16/27

⚫문제


🟡생각
최대한 약분하여 출력한다 -> 기약분수의 형태로 출력한다.(사실 분수형태는 아니라서 기약분수라고 할 수는 없지만 그냥 쉽게 생각해서 기약분수라고 표현했다.)
기약분수는, 분자와 분모의 최대공약수로 서로 나누어 더이상 나눌 수 없을때까지 약분한 분수이다.

그렇다면 최대공약수는 어떻게 구할까? GCD (Greatest Common Divisor)는 최대공약수라는 뜻이며, 두 자연수의 가장 큰 공통된 약수라고 뜻한다. GCD 알고리즘은 유클리드 호제법을 사용하는것으로 유명하다.

유클리드 호제법이란 간단하게 O(logN)의 시간복잡도로 두 자연수의 최대 공약수를 구할 수 있는 알고리즘이다.

기존의 방법(브루트 포스)도 O(N)의 시간복잡도로 나쁘지는 않지만 효율을 높히기 위해 이 알고리즘을 사용한다.

a를 b로 나눈 나머지를 r이라고 할때 (단, a > b) a와 b의 최대 공약수는 b와 r의 최대 공약수와 같다는 성질을 이용한다.

이런 성질을 통해서 b와 r의 최대 공약수 r0를 구하고, 다시 r을 r0로 나눈 나머지를 구하는 과정을 반복하여(recursive) 나머지가 0이 되었을 때의 그 몫이 a와 b의 최대 공약수이다.
이를 수식으로 나타내면 아래와 같다.

  GCD(A, B) = GCD(B, A%B)
      if A%B = 0 -> GCD = B
          else GCD(B, A%B)

재귀로 반복하여 구한다.

나는 C++ STL의 numeric 컨테이너를 사용해서 gcd함수를 사용했다.


🟢 구현

#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
using namespace std;

#define fastIo                      \
  ios_base::sync_with_stdio(false); \
  cin.tie(NULL);                    \
  cout.tie(NULL);

string str;
string s1;
string s2;
bool flag = false;

int main() {
  fastIo;

  cin >> str;
  for (int i = 0; i < str.length(); i++) {
    if (str[i] == ':') {
      flag = true;
    }

    if (!flag) {
      s1 += str[i];
    } else {
      // 이 코드가 있어야 s2에 ':' 이게 안들어가 ㅇㅇ
      if (str[i] != ':') {
        s2 += str[i];
      }
    }
  }

  //   cout << s1 << "\n";
  //   cout << s2 << "\n";
  int ss1 = stoi(s1);
  int ss2 = stoi(s2);
  int ggcd = gcd(ss1, ss2);

  cout << ss1 / ggcd << ":" << ss2 / ggcd;

  return 0;
}

중간에 콜론(':') 때문에 조금 애먹었지만 금방 해결했다~

profile
근 성

0개의 댓글