Computer Science
탄탄한 기반 실력을 위한
전공과 이론 지식 모음
Today I Learned!
배웠으면 기록을 해야지
TIL 사진
Flutter 사진
Flutter로 모바일까지
거꾸로캠퍼스 코딩랩 Flutter 앱개발 강사
스파르타코딩클럽 즉문즉답 튜터
카카오테크캠퍼스 3기 학습코치
프로필 사진
박성민
임베디드 세계에
발을 들인 박치기 공룡
임베디드 사진
EMBEDDED SYSTEM
임베디드 SW와 HW, 이론부터 실전까지
ALGORITHM
알고리즘 해결 전략 기록
🎓
중앙대학교 소프트웨어학부
텔레칩스 차량용 임베디드 스쿨 3기
애플 개발자 아카데미 1기
깃허브 사진
GitHub
프로젝트 모아보기
Instagram
인스타그램 사진

Develop/알고리즘

[백준] 3036 - 링

sm_amoled 2022. 1. 4. 20:16

문제링크

https://www.acmicpc.net/problem/3036

문제

상근이는 창고에서 링 N개를 발견했다. 상근이는 각각의 링이 앞에 있는 링과 뒤에 있는 링과 접하도록 바닥에 내려놓았다.

상근이는 첫 번째 링을 돌리기 시작했고, 나머지 링도 같이 돌아간다는 사실을 발견했다. 나머지 링은 첫 번째 링 보다 빠르게 돌아가기도 했고, 느리게 돌아가기도 했다. 이렇게 링을 돌리다 보니 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 도는지 궁금해졌다.

링의 반지름이 주어진다. 이때, 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 돌아가는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 링의 개수 N이 주어진다. (3 ≤ N ≤ 100)

다음 줄에는 링의 반지름이 상근이가 바닥에 놓은 순서대로 주어진다. 반지름은 1과 1000를 포함하는 사이의 자연수이다.

출력

출력은 총 N-1줄을 해야 한다. 첫 번째 링을 제외한 각각의 링에 대해서, 첫 번째 링을 한 바퀴 돌리면 그 링은 몇 바퀴 도는지 기약 분수 형태 A/B로 출력한다.

조건

  • 시간 제한 : 1s
  • 메모리 제한 : 128MB

해설

첫번째 링의 반지름을 A, 나머지 링들 중 하나의 반지름을 B라고 한다면 출력해야하는 결과값은 A/B를 약분하여 기약분수의 형태로 나타낸 꼴이다. 더이상 약분할 수 없을 때까지 약분하는 것은 A와 B의 값에 최대공약수를 나누는 것과 같으므로, 입력 값 B에 대해 A와의 최대공약수를 구해 나누어 결과를 적절히 출력해주면 된다.

최대공약수를 구하기 위해서는 a, b 값을 인자로 받아와서 두 수가 같아질 때 까지 두 수 중 큰 수에서 작은 수의 값을 빼어 큰 수를 대치해준다. 이 과정을 반복하면 최대공약수를 얻을 수 있다.

수학적인 원리는 다음과 같다.
A, B가 있을 때 A > B 이며, 이 두 수의 최대공약수가 C라고 하자.
A = a x C, B = b x C 라고 할 수 있다.

A > B 이므로,
A-B = (a-b) x C, B = b x C

A-B < B 라고 하면
A-B = (a-b) x C, B-(A-B) = (2b - a) x C
...

~~~ = 1 x C, ~~~ = 1 x C 가 되는 순간, 양쪽의 수가 같아지며, 두 수가 모두 C의 배수이므로 이렇게 구한 C가 A, B의 최대공약수이다.

풀이

최대공약수를 구하기 위한 함수를 아래와 같이 선언해주었다. a, b 값을 인자로 받아와서 두 수가 같아질 때 까지 두 수 중 큰 수에서 작은 수의 값을 빼어 큰 수를 대치한다. 이 과정을 반복하면 최대공약수를 얻을 수 있다. a, b의 값이 같을 때 반복문을 탈출하므로, 둘 중 어느 수든 반환해주면 된다.

int getGCD(int a, int b) {
    while(a != b) {
        if(a < b) {b = b-a;}
        else {a = a-b;}
    }
    
    return a;
}

제일 첫번째 링이 회전량의 기준이 되므로, first 변수에 저장해준다. 다음 입력부터는 input 변수에 입력을 받고, first와 input의 최대공약수를 이용해 기약분수 꼴로 변환하여 출력해준다.

cin >> first;
for(int i = 1; i < N; i++) {
    int input;
    cin >> input;
    
    int gcd = getGCD(first, input);
    cout << first/gcd << '/' << input/gcd <<'\n';
}


코멘트

난 내가 지금까지 쓰고있던 저 GCD 구하는 알고리즘이 유클리드 호제법인줄 알았는데, 방금 검색해보니까 완전 다르네..? 성능은 모르겠지만, 이해하기 쉽고 간편한 건 내 방식인 것 같다. ㅎㅎ 저것도 분명 어떤 이름이 있겠지.


코드

#include <iostream>

using namespace std;

int getGCD(int a, int b) {
    while(a != b) {
        if(a < b) {b = b-a;}
        else {a = a-b;}
    }
    
    return a;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int N, first;
    cin >> N;
    
    cin >> first;
    for(int i = 1; i < N; i++) {
        int input;
        cin >> input;
        
        int gcd = getGCD(first, input);
        cout << first/gcd << '/' << input/gcd <<'\n';
    }
     
    return 0;
}
320x100

'Develop > 알고리즘' 카테고리의 다른 글

[백준] 11050 - 이항 계수 1  (0) 2022.01.04
[백준] 9375 - 패션왕 신해빈  (0) 2022.01.04
[백준] 14888 - 연산자 끼워넣기  (0) 2021.12.26
[백준] 1541 - 잃어버린 괄호  (0) 2021.12.26
[백준] 1037 - 약수  (0) 2021.12.26