μ•Œκ³ λ¦¬μ¦˜

[Java] BOJ 6064 μΉ΄μž‰ 달λ ₯

🍊귀🍊 2024. 8. 25. 18:46

문제 

문제 링크 https://www.acmicpc.net/problem/6064

  • μ΅œκ·Όμ— ICPC νƒμ‚¬λŒ€λŠ” λ‚¨μ•„λ©”λ¦¬μΉ΄μ˜ μž‰μΉ΄ 제ꡭ이 λ†€λΌμš΄ λ¬Έλͺ…을 μ§€λ‹Œ μΉ΄μž‰ μ œκ΅­μ„ ν† λŒ€λ‘œ ν•˜μ—¬ μ„Έμ›Œμ‘Œλ‹€λŠ” 사싀을 λ°œκ²¬ν–ˆλ‹€. μΉ΄μž‰ 제ꡭ의 백성듀은 νŠΉμ΄ν•œ 달λ ₯을 μ‚¬μš©ν•œ κ²ƒμœΌλ‘œ μ•Œλ €μ Έ μžˆλ‹€.
  • 그듀은 Mκ³Ό N보닀 μž‘κ±°λ‚˜ 같은 두 개의 μžμ—°μˆ˜ x, yλ₯Ό κ°€μ§€κ³  각 년도λ₯Ό <x:y>와 같은 ν˜•μ‹μœΌλ‘œ ν‘œν˜„ν•˜μ˜€λ‹€.
  • 그듀은 이 μ„Έμƒμ˜ μ‹œμ΄ˆμ— ν•΄λ‹Ήν•˜λŠ” 첫 번째 ν•΄λ₯Ό <1:1>둜 ν‘œν˜„ν•˜κ³ , 두 번째 ν•΄λ₯Ό <2:2>둜 ν‘œν˜„ν•˜μ˜€λ‹€. <x:y>의 λ‹€μŒ ν•΄λ₯Ό ν‘œν˜„ν•œ 것을 <x':y'>이라고 ν•˜μž.
  • 만일 x < M 이면 x' = x + 1이고, κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ x' = 1이닀.
  • 같은 λ°©μ‹μœΌλ‘œ 만일 y < N이면 y' = y + 1이고, κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ y' = 1이닀. <M:N>은 κ·Έλ“€ 달λ ₯의 λ§ˆμ§€λ§‰ ν•΄λ‘œμ„œ, 이 해에 μ„Έμƒμ˜ 쒅말이 λ„λž˜ν•œλ‹€λŠ” μ˜ˆμ–Έμ΄ μ „ν•΄ μ˜¨λ‹€.
  • 예λ₯Ό λ“€μ–΄, M = 10 이고 N = 12라고 ν•˜μž. 첫 번째 ν•΄λŠ” <1:1>둜 ν‘œν˜„λ˜κ³ , 11번째 ν•΄λŠ” <1:11>둜 ν‘œν˜„λœλ‹€. <3:1>은 13번째 ν•΄λ₯Ό λ‚˜νƒ€λ‚΄κ³ , <10:12>λŠ” λ§ˆμ§€λ§‰μΈ 60번째 ν•΄λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • λ„€ 개의 μ •μˆ˜ M, N, x와 yκ°€ μ£Όμ–΄μ§ˆ λ•Œ, <M:N>이 μΉ΄μž‰ 달λ ₯의 λ§ˆμ§€λ§‰ 해라고 ν•˜λ©΄ <x:y>λŠ” λͺ‡ 번째 ν•΄λ₯Ό λ‚˜νƒ€λ‚΄λŠ”μ§€ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λΌ.
  • μž…λ ₯ λ°μ΄ν„°λŠ” ν‘œμ€€ μž…λ ₯을 μ‚¬μš©ν•œλ‹€. μž…λ ₯은 T개의 ν…ŒμŠ€νŠΈ λ°μ΄ν„°λ‘œ κ΅¬μ„±λœλ‹€.
  • μž…λ ₯의 첫 번째 μ€„μ—λŠ” μž…λ ₯ λ°μ΄ν„°μ˜ 수λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ •μˆ˜ Tκ°€ μ£Όμ–΄μ§„λ‹€. 각 ν…ŒμŠ€νŠΈ λ°μ΄ν„°λŠ” ν•œ μ€„λ‘œ κ΅¬μ„±λœλ‹€.
  • 각 μ€„μ—λŠ” λ„€ 개의 μ •μˆ˜ M, N, x와 yκ°€ μ£Όμ–΄μ§„λ‹€. (1 ≤ M, N ≤ 40,000, 1 ≤ x ≤ M, 1 ≤ y ≤ N) μ—¬κΈ°μ„œ <M:N>은 μΉ΄μž‰ 달λ ₯의 λ§ˆμ§€λ§‰ ν•΄λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • 좜λ ₯은 ν‘œμ€€ 좜λ ₯을 μ‚¬μš©ν•œλ‹€. 각 ν…ŒμŠ€νŠΈ 데이터에 λŒ€ν•΄, μ •μˆ˜ kλ₯Ό ν•œ 쀄에 좜λ ₯ν•œλ‹€.
  • μ—¬κΈ°μ„œ kλŠ” <x:y>κ°€ k번째 ν•΄λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 것을 μ˜λ―Έν•œλ‹€. 만일 <x:y>에 μ˜ν•΄ ν‘œν˜„λ˜λŠ” ν•΄κ°€ μ—†λ‹€λ©΄, 즉, <x:y>κ°€ μœ νš¨ν•˜μ§€ μ•Šμ€ ν‘œν˜„μ΄λ©΄, -1을 좜λ ₯ν•œλ‹€.

     

아이디어

  • μΉ΄μž‰ 달λ ₯의 κΈ°μ€€ μ‹œκ°„μΈ Mκ³Ό N의 μ΅œμ†Œκ³΅λ°°μˆ˜λ₯Ό ꡬ해쀀닀. (μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²•μ„ μ΄μš©ν•˜μ—¬)
  • 그리고 i값을 (x - 1)κ°’μœΌλ‘œ μ‹œμž‘μ μ„ 작고 μ΅œμ†Œκ³΅λ°°μˆ˜ μ „κΉŒμ§€ M만큼 μ¦κ°€μ‹œν‚€λ©΄μ„œ λ°˜λ³΅ν•œλ‹€. ((x - 1)값을 μ‹œμž‘μ μœΌλ‘œ μž‘λŠ” μ΄μœ λŠ” μ΅œμ†Œκ³΅λ°°μˆ˜μ™€ μ‹œμž‘μ μ΄ 같은 숫자일 경우, 반볡문 μžμ²΄κ°€ λŒμ•„κ°€μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€. => 예λ₯Ό λ“€μ–΄ M, N, x, y 값이 λ‹€ 같을 경우)
  • λ§Œμ•½ i값을 N으둜 λ‚˜λˆ΄μ„ λ•Œ, λ‚˜λ¨Έμ§€κ°€ (y - 1)이라면 (x값을 -1ν•΄μ€¬μœΌλ―€λ‘œ y값도 λ˜‘κ°™μ΄ 빼쀌) μΉ΄μž‰ 달λ ₯으둜 λ§Œλ“€ 수 μžˆλ‹€λŠ” λœ»μ΄λ―€λ‘œ 결과값에 i값에 1을 더해쀀 값을 μ €μž₯ν•˜κ³  λ°˜λ³΅λ¬Έμ„ μ’…λ£Œν•œλ‹€. (x, y값에 1을 λΉΌμ€¬μœΌλ―€λ‘œ 결과값에도 1을 더해쀀닀.)

κ²ͺ은 μ‹œν–‰μ°©μ˜€

  • μ΅œλŒ€κ³΅μ•½μˆ˜μ™€ μ΅œμ†Œκ³΅λ°°μˆ˜λ₯Ό ν™œμš©ν•˜λŠ” 문제인 것을 계속 μ μ–΄λ³΄λ©΄μ„œ λ’€λŠ¦κ²Œ λ°œκ²¬ν–ˆλ‹€... (μƒλ‹Ήνžˆ μ‹œκ°„μ΄ κ±Έλ Έλ‹€.. γ…œ)
  • κ·Έλ§ˆμ €λ„ μ²˜μŒμ—λŠ” μ΅œμ†Œκ³΅λ°°μˆ˜κ°€ μ•„λ‹ˆλΌ μ΅œλŒ€κ³΅μ•½μˆ˜λ₯Ό ν™œμš©ν•˜λŠ” λ¬Έμ œμΈμ€„ μ•Œκ³  κ·Έλ ‡κ²Œ ν’€λ‹€κ°€ μ˜ˆμ œκ°€ 잘 λ§žμ§€ μ•Šμ•„ λ‹€μ‹œ ν’€μ—ˆλ‹€... (γ…œγ…œ)
  • κ·Έλ ‡κ²Œ ν‘Ό μ½”λ“œλ„ 처음 μ œμΆœν–ˆμ„ λ•ŒλŠ” 'ν‹€λ ΈμŠ΅λ‹ˆλ‹€'κ°€ 뜨길래 λ‹Ήν™©ν–ˆλ‹€.
  • μ˜ˆμ œλŠ” λ‹€ λ§žμ•˜λŠ”λ° μ™œ ν‹€λ Έμ§€ν•˜κ³  λ°˜λ‘€λ₯Ό μ°Ύμ•„λ³΄λ‹ˆ M, N, x, yκ°€ λͺ¨λ‘ 같은 숫자일 경우, λ°˜λ³΅λ¬Έμ„ λ“€μ–΄κ°€μ§€ λͺ»ν•΄ 무쑰건 -1을 좜λ ₯ν•œλ‹€λŠ” κ²ƒμ΄μ˜€λ‹€. (μ΅œμ†Œκ³΅λ°°μˆ˜μ™€ x, yκ°€ 같은 경우)
  • κ·Έλž˜μ„œ λ°˜λ³΅λ¬Έμ— λ“€μ–΄κ°ˆ 수 μžˆλ„λ‘ x, y값에 -1을 ν•΄μ£Όμ–΄ μ˜ˆμ™Έκ°€ 없도둝 ν•˜κ³  결과값을 ꡬ할 λ•Œ λΊ€ -1을 λ‹€μ‹œ 더해주도둝 μˆ˜μ •ν•˜μ˜€λ‹€.

생각보닀 μ‰½κ²Œ 풀리지 μ•Šμ•„ νž˜λ“€μ—ˆλ˜ λ¬Έμ œμ˜€λ‹€....γ…œγ…œγ…œ

μ½”λ“œ

import java.io.*;
import java.util.*;

public class BOJ6064 {

    static int gcd;

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int T = Integer.parseInt(br.readLine());

        for(int test = 0; test < T; test++){
            StringTokenizer st = new StringTokenizer(br.readLine());

            // 연도 κΈ°μ€€
            int M = Integer.parseInt(st.nextToken());
            int N = Integer.parseInt(st.nextToken());

            // μΉ΄μž‰ 달λ ₯으둜 ꡬ할 ν•΄
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());

            // μ΅œλŒ€κ³΅μ•½μˆ˜λ₯Ό μ €μž₯ν•  λ³€μˆ˜
            gcd = 0;
            // μ΅œλŒ€κ³΅μ•½μˆ˜ κ΅¬ν•˜κΈ°
            GCD(M, N);

            // μ΅œμ†Œκ³΅λ°°μˆ˜λ₯Ό μ €μž₯ν•  λ³€μˆ˜
            int lcm = 0;
            // μ΅œμ†Œκ³΅λ°°μˆ˜ κ΅¬ν•˜κΈ°
            lcm = (M * N)/gcd;

            // κ²°κ³Όκ°’ μ €μž₯ λ³€μˆ˜
            // ν•΄λ‹Ήλ˜λŠ” μΉ΄μž‰ 달λ ₯ 년도가 μ—†λ‹€λ©΄ -1을 좜λ ₯ν•΄μ•Όλ˜λ―€λ‘œ
            // -1둜 μ΄ˆκΈ°ν™”
            int result = -1;

            // x값을 κΈ°μ€€μœΌλ‘œ μ΅œμ†Œκ³΅λ°°μˆ˜ μ „κΉŒμ§€ 반볡
            // i값은 xκ°’μœΌλ‘œ μ‹œμž‘ν•΄μ„œ Mκ°’λ§ŒνΌ 계속 μ¦κ°€μ‹œν‚΄
            // μ΅œμ†Œκ³΅λ°°μˆ˜μ™€ x, y값이 λͺ¨λ‘ 같을 경우 ν•΄λ‹Ή λ°˜λ³΅λ¬Έμ„
            // μ§„ν–‰ν•˜μ§€ λͺ»ν•˜λ―€λ‘œ x, y값에 -1μ²˜λ¦¬ν•˜κ³  돌림
            for(int i = (x - 1); i < lcm; i = i + M){
                // i값을 N으둜 λ‚˜λˆ΄μ„λ•Œ, λ‚˜λ¨Έμ§€ 값이 yκ°’μœΌλ‘œ λ‚˜μ˜¨λ‹€λ©΄
                if(i % N == (y - 1)){
                    // result값을 i둜 μ €μž₯ν•˜κ³ 
                    // μœ„μ—μ„œ x, y값에 -1을 ν–ˆμœΌλ―€λ‘œ + 1을 ν•΄μ€Œ
                    // 반볡문 μ’…λ£Œ
                    result = i + 1;
                    break;
                }
            }

            sb.append(result + "\n");
        }

        System.out.println(sb);
    }

    public static void GCD(int n1, int n2){
        // n1이 n2둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§„λ‹€λ©΄ n2κ°€ 두 수의 μ΅œλŒ€κ³΅μ•½μˆ˜μ΄λ―€λ‘œ
        // μ΅œλŒ€κ³΅μ•½μˆ˜λŠ” n2κ³  ν•¨μˆ˜ μ’…λ£Œ
        if(n1 % n2 == 0){
            gcd = n2;
            return;
        }

        // λ§Œμ•½ λ‚˜λˆ„μ–΄λ–¨μ–΄μ§€μ§€ μ•ŠλŠ”λ‹€λ©΄ μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²•μ„ μ΄μš©ν•΄μ„œ
        // n2와 n1을 n2둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€λ‘œ
        // ν•¨μˆ˜λ₯Ό λ‹€μ‹œ 돌림
        GCD(n2, n1 % n2);
    }
}