ABOUT ME

주로 개발 관련해 이것저것 작성중입니다.

Today
Yesterday
Total
  • Q. 1637 자바 : 날카로운 눈
    코딩테스트/백준_Java 2025. 3. 2. 23:32

    Q. 1637 자바 : 날카로운 눈

     

    문제 : boj.kr/1637

    P4 난이도의 문제이다.

     

    문제를 간단히 설명하자면 n개의 입력이 주어지고 입력마다 a, c, b가 주어진다.

    각각의 입력에 대해 a, a + b, ... a+kb(a + kb <= c)인 숫자를 모두 하나의 정수 더미에 넣었을 때

    특정한 정수 하나만 홀수개 존재한다면 그 정수와 몇개 존재하는지를 구하는 문제이다.

     

    예를들어 아래와 같이 입력이 주어졌다면

    4
    1 10 1
    4 4 1
    1 5 1
    6 10 1

    첫 번째 입력은 1, 2, 3, 4, 5, 6, 7, 8, 9, 10의 정수 더미를

    두 번째 입력은 4

    세 번째는 1, 2, 3, 4, 5

    네 번째는 6, 7, 8, 9, 10을 의미한다.

     

    이를 모두 합치면 정수 4가 3개 존재하므로 4 3을 출력하면 된다.


    먼저 완전 탐색 방식으로 푼다고 가정하면 아래와 같이 풀었을 것 같다.

    1. 위 예시와 마찬가지로 모든 입력들에 대해 정수 더미를 만든다.

    2. 정수 더미를 정렬한다.

    3. 정수 더미를 하나씩 세며 홀수 개 있는 정수를 계산한다.

     

    이렇게 푼다면 정수 a, b, c의 범위가 약 21억 이므로 1번 과정만 약 21억번의 계산이 필요하다.

    시간제한은 2초이므로 이 방법은 불가능해 보였다.

    그래서 완전 탐색이 아닌 다른 방법을 생각해야 한다.


    먼저 입력의 수 n이 20,000이므로 O(n) 또는 O(n logn) 정도면 풀 수 있을 것 같다.

    그리고 이 정수 더미들의 집합은 이분 탐색의 특징을 보이는데, 정렬된 정수 더미에서 특정 정수 x 이하인 숫자들을 셌을 때 짝수개인지 홀수개인지만 판단한다면 구간을 줄이는 방식으로 풀 수 있다.

     

    즉 정수 x를 정하고  정렬된 정수 더미에서 x이하인 숫자들을 셌을 때 짝수개인지 홀수개인지만 판단하는 결정 문제로 바꿀 수 있다.

    이 경우 정수 x는 약21억이고 n개의 정수 더미가 존재하므로 O(n logx)의 시간복잡도로 풀 수 있다.

    log x는 약 30정도이므로 O(n)으로 봐도 될 것 같다.

     

    아래와 같은 방식으로 풀었다.

    1. 정수 x에 대해 이분탐색을 한다. - O(log x)

    2. 결정 문제는 x 이하인 정수 더미가 홀수개인가? 이다. -  O(n)

    2-1. 이 때 x 이하인 정수 더미의 숫자가 int 범위를 초과할 수 있으므로 주의해야 한다. 

     

    import java.io.*;
    import java.util.*;
    
    public class Main {
    
        static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        static StringBuilder sb = new StringBuilder();
        static StringTokenizer st;
    
        static int[][] inputNum;
        static int n;
    
        static void input() throws IOException {
            n = Integer.parseInt(br.readLine());
    
            inputNum = new int[n][3];
            for (int i = 0; i < n; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < 3; j++) {
                    inputNum[i][j] = Integer.parseInt(st.nextToken());
                }
            }
        }
    
        static long count(int a, int c, int b, long mid) {
            if (mid < a) return 0;
            int res = 1;
    
            if (c < mid) res += (c - a) / b;
            else res += (mid - a) / b;
    
            return res;
        }
    
        static boolean determination(long mid) {
            long sum = 0;
            for (int i = 0; i < n; i++) {
                sum += count(inputNum[i][0], inputNum[i][1], inputNum[i][2], mid);
            }
            return sum % 2 == 1;
        }
    
        static void pro() {
            long left = 1, right = Integer.MAX_VALUE, ans = 0;
    
            while (left <= right) {
                long mid = (left + right) / 2;
    
                if (determination(mid)) {
                    ans = mid;
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
    
            int sum = 0;
            for (int i = 0; i < n; i++) {
                int a = inputNum[i][0];
                int c = inputNum[i][1];
                int b = inputNum[i][2];
    
                long ansMinA = ans - a;
                if (0 <= ansMinA && ans <= c && (ansMinA % b == 0)) sum++;
            }
    
            if (sum % 2 == 1) {
                sb.append(ans).append(' ').append(sum);
            } else {
                sb.append("NOTHING");
            }
            System.out.println(sb);
        }
    
        public static void main(String[] args) throws Exception {
            input();
            pro();
        }
    }

     

    반응형

    '코딩테스트 > 백준_Java' 카테고리의 다른 글

Designed by Tistory.