[ 백준 ] 2168 / 타일 위의 대각선

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
129/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 2168 / 타일 위의 대각선
 *
 * Kind :: Math
 *
 * Insight
 * - 주어진 예제 입력 (8, 12) 를 그려보면
 *   (2, 3) 과 같은 모양이 4번 반복됨을 알 수 있다
 *   + 대각선이 아래로 2칸, 오른쪽으로 3칸 그려질 때마다
 *     타일의 변이 아닌 꼭짓점에 닿게 되고
 *     이러한 양상이 gcd(8, 12) = 4번 반복된다
 *
 * - 그렇다면 (2, 3) 과 같이 각 변의 길이가 서로소일 때
 *   대각선이 몇 개의 칸을 지나는 가?
 *   + 일단 대각선은 출발지점과 도착지점외에 다른 꼭짓점을 지나지 않는다
 *     즉, 대각선은 오직 타일의 변만 지난다
 *     # 가로변의 길이가 세로변의 길이보다 더 길면 칸의 세로줄을 먼저 만난다
 *       대각선의 시작 꼭짓점이 가로변을 만난다고 간주하면,
 *       대각선의 경로는
 *       (가로변:출발) -> (세로줄) -> (가로줄) -> ... -> (세로줄) -> (가로변:도착)
 *       위처럼 볼 수 있다
 *     # 세로변의 길이가 가로변의 길이보다 더 길면 칸의 가로줄을 먼저 만난다
 *       대각선의 시작 꼭짓점이 세로변을 만난다고 간주하면,
 *       대각선의 경로는
 *       (세로변:출발) -> (가로줄) -> (세로줄) -> ... -> (가로줄) -> (세로변:도착)
 *       위처럼 볼 수 있다
 *       -> 대각선의 경로에서 인접한 두 원소를 하나로 묶으면 지나는 칸을 뜻하게 된다
 *          가로변또한 가로줄로, 세로변도한 세로줄로 간주하면
 *          지나는 칸의 개수는 (가로줄의 개수 + 세로줄의 개수 - 1) 이 된다
 *       -> 즉, (n, m) 이고 n 과 m 이 서로소라면
 *          이때 대각선이 지나는 칸의 개수는 (n+m-1) 이다
 *
 * Point
 * - Overflow 위험이 있으니 long 을 사용하도록 합시다
 *
 * - gcd 구할 때는 유클리드 호제법을 사용하도록 합시다
 *   + gcd(x, y) 는 gcd(y, x%y) 와 같다!
 *
 * - C++17 에서는
 *   #include <numeric>
 *   gcd(x, y)
 *   로 쉽게 최대공약수를 쉽게 구할 수 있습니다
 *   + lcm(x, y)
 *     도 있어 최소공배수를 쉽게 구할 수 있습니다
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>

using namespace std;

#define endl '\n'

// Set up : Global Variables
/* None */

// Set up : Functions Declaration
long getGCD(long n, long m);


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    long x, y;
    cin >> x >> y;

    // Process
    long gcd = getGCD(x, y);
    long cox = x / gcd;
    long coy = y / gcd; /* cox 와 coy 는 서로소 */ 

    // Control : Output
    /* gcd 만큼 반복, (cox, coy) 에서 대각선이 지나는 칸의 개수는 (cox+coy-1) */
    cout << gcd * (cox+coy-1) << endl;
}

// Helper Functions
long getGCD(long n, long m)
/* n 과 m 의 최대공약수를 반환 */
{
    while (m) {
        long r = n % m;
        n = m;
        m = r;
    } return n;
}
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글