반응형
문제 요약
여러 명의 플레이어가 각각 1~1,000,000 사이의 서로 다른 수가 적힌 카드를 한 장씩 받습니다.
각 플레이어는 본인을 제외한 모든 플레이어와 한 번씩 결투를 하며,
- 내 카드의 수로 상대의 수를 나누어 떨어지면 승리(+1점),
- 반대로 상대가 내 수를 나누어 떨어뜨리면 패배(-1점),
- 둘 다 아니면 무승부(점수 변화 없음)
이렇게 모든 결투가 끝난 뒤, 각 플레이어의 최종 점수를 구하는 문제입니다.
접근 방식
처음에는 모든 플레이어 쌍을 비교하는 완전탐색을 떠올릴 수 있습니다.
하지만 플레이어 수 N이 최대 100,000명, 카드 숫자 범위도 1,000,000까지라서
O(N²) 방식은 시간 초과가 발생합니다.
여기서 "나누어 떨어진다"는 조건에 주목하면,
각 카드의 배수(2배, 3배, ...)가 다른 플레이어의 카드에 있다면
그 배수 카드를 가진 플레이어에게 승리할 수 있습니다.
즉,
- 내 카드의 배수에 해당하는 카드가 있다면 나는 +1점, 그 상대는 -1점
- 이 과정을 모든 카드에 대해 반복
이렇게 하면 불필요한 비교 없이 효율적으로 점수를 계산할 수 있습니다.
실생활 비유로 설명하면,
"내가 가진 숫자의 배수만 찾아서 그 사람만 이긴다"는 식으로
불필요한 결투(비교)를 피하는 셈입니다.
코드 구현
아래는 Python으로 구현한 코드입니다.
핵심 부분마다 주석을 달아 이해를 돕습니다.
import sys
input = sys.stdin.readline
N = int(input())
cards = list(map(int, input().split()))
max_card = max(cards)
card_set = set(cards) # 카드가 실제로 존재하는지 빠르게 확인
# 각 카드별 점수 기록용 딕셔너리
value_score = {card: 0 for card in cards}
for card in cards:
multiple = card * 2
# 내 카드의 배수들만 탐색
while multiple <= max_card:
if multiple in card_set:
value_score[card] += 1 # 나는 이긴다
value_score[multiple] -= 1 # 상대는 진다
multiple += card
# 결과 출력 (입력 순서대로)
print(' '.join(str(value_score[card]) for card in cards))
시간복잡도 & 최적화
- 시간복잡도:
- 각 카드마다 자신의 배수(최대 1,000,000까지)를 탐색하므로
전체적으로 약 O(N log M) 수준 (M: 카드 숫자 최대값)
- 각 카드마다 자신의 배수(최대 1,000,000까지)를 탐색하므로
- 최적화 포인트:
- 카드가 실제로 존재하는지 빠르게 확인하기 위해 set 자료구조 사용
- 불필요한 모든 쌍 비교를 배수 관계로만 한정하여 연산량 대폭 감소
느낀 점 / 팁
- "모든 쌍을 비교"하는 문제는 반드시 효율적인 조건(여기선 배수 관계)을 찾아내야 합니다.
- set을 활용하면 "존재 여부"를 O(1)로 빠르게 확인할 수 있어,
대량의 데이터 처리에 매우 유용합니다. - 배수 관계 문제는 종종 "에라토스테네스의 체"와 비슷한 아이디어로 접근하면
시간복잡도를 크게 줄일 수 있습니다.
참고
반응형
'Algorithm > 백준' 카테고리의 다른 글
[백준 / 2342 / Python] Dance Dance Revolution (0) | 2025.06.13 |
---|---|
[백준 / 2143 / Python] 두 배열의 합 (0) | 2025.06.13 |
[백준 / 1647 / Python] 도시 분할 계획 (0) | 2025.06.10 |
[백준 / 27440 / Python] 1 만들기 (0) | 2025.05.30 |
[백준 / 13705 / Python] Ax+Bsin(x)=C (0) | 2025.05.30 |