문제 풀이/백준

[백준] 1241번. 머리 톡톡(JAVA)

27200 2025. 3. 18. 21:17

문제

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


풀이(15분)

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(br.readLine());
        int[] numbers = new int[n + 1];
        HashMap<Integer, Integer> frequencyMap = new HashMap<>();
        
        for (int i = 1; i <= n; i++) {
            int inputNumber = Integer.valueOf(br.readLine());
            numbers[i] = inputNumber;
            frequencyMap.put(inputNumber, frequencyMap.getOrDefault(inputNumber, 0) + 1);
        }

        int[] divisorCount = new int[1_000_001];
        for (int num : frequencyMap.keySet()) {
            int count = 0;

            if (num <= 1) {
                count = frequencyMap.get(num) - 1;
            } else {
                for (int i = 1; i <= Math.sqrt(num); i++) {
                    if (num % i == 0) {
                        if (frequencyMap.containsKey(i)) count += frequencyMap.get(i);
                        int pair = num / i;
                        if (frequencyMap.containsKey(pair)) {
                            count += frequencyMap.get(pair);
                            if (pair == num) count--;
                            if (pair == i) count -= frequencyMap.get(i);
                        }
                    }
                }
            }
            divisorCount[num] = count;
        }

        for (int i = 1; i <= n; i++) {
            System.out.println(divisorCount[numbers[i]]);
        }
    }
}

문제 풀이 전략

 

사용된 자료구조보다는 아이디어가 중요한 문제 같아 그 부분에 초점을 두고 풀어보자.

 

숫자를 입력받았을 때, 자기를 때릴 수 있는 수들을 계산하는 것이다.

즉, 약수를 구하자는 것이다.

 

n = 100,000으로 이미 크다. 거기에 숫자도 1,000,000까지 가능하니 모두 탐색하는 것은 불가능하다.

하지만 에라토스테네스의 체와 동일한 원리로 약수를 찾을 때도 제곱근까지만 해도 된다는 것을 알아야 한다.

-> 모든 자연수는 (제곱근) * (제곱근) 의 조합을 갖게 된다. 이 경우 두 수의 곱 중 반드시 하나는 제곱근 이하의 수가 된다.

-> 한 쪽의 수를 제곱근 범위까지만 탐색하면 된다!

 

위와 같은 원리로 인해 제곱근까지만 탐색을 한 뒤, map에 저장하여 정답을 탐색하면 된다.