백준 비드맨(19590)

axiom·2021년 7월 11일
1

비드맨

1. 힌트

1) 언제나 가장 많이 있는 구슬 종류 두 가지를 부딪히는 것이 이득입니다.

2) max(S)sum(S)max(S)max(S) \ge sum(S) - max(S)라면 답은 자명합니다.

3) 위 조건을 만족하지 않으면 전체 합이 짝수면 모두 없앨 수 있고 홀수면 한 개가 남습니다.

2. 접근

1) 단순한 방법에서 시작할 수 있을까?

단순하게 생각해 보면 부딪힐 때마다 한 번에 2개 씩 없어지니 짝수면 다 없앨 수 있고 홀수면 한 개가 남을 것 같습니다. 하지만 그 생각은 에제 입력 2에서 무너집니다.

그렇다면 손으로 직접 해보겠습니다. 예제 입력 3을 보니 22끼리 먼저 부딪히면 44가 남습니다. 하지만 최적해는 4422를 부딪히고 이제 남은 22끼리 부딪혀서 모두 없애는거죠. 언제나 가장 큰 것 2개를 부딪히는 것이 최적해인 것 같습니다. 어떻게 증명할 수 있을까요?

여러가지 상황이 있겠지만 우리가 근본적으로 피하고자 하는 상황은 다음과 같은 형태입니다.
(1, 1, x)(1,\ 1,\ x) 여기에서 11끼리 먼저 부딪히는 바람에 xx가 고스란히 남게 되는것이죠. 가장 큰 것 2개를 부딪히는 방법은 절대로 이와 같은 선택을 하지 않습니다. x2x \ge 2라고 가정해보겠습니다. 그러면 우리의 해법은 xx11을 부딪히게 되고 이제 x1x-111이 남습니다. xx11이라면 뭐 어떻게 부딪혀도 다 똑같죠. 그러므로 가장 큰 것 2개를 부딪히는 방법은 절대로 손해를 보지 않습니다.

그래서 이 방법대로 구현하려고 보니... 입력의 크기가 문제입니다. 가장 큰 것 2개를 뽑아내는 방법은 우선 순위 큐로 쉽게 구현해서 O(NlgN)O(NlgN)에 구현 할 수 있습니다. 그런데 구슬의 최대 개수는 101410^{14}입니다. 직접 최적해를 실행 하는 것은 불가능합니다. 다른 방법이 있다는거겠죠 문제를 좀 더 관찰해봅시다.

최적해로 구슬을 부딪히면 언제나 단 한 종류의 구슬만 남거나 하나도 남지 않습니다. 두 종류 이상으로 남는다면 두 개를 부딪혀서 한 종류를 없앨 수 있기 때문이죠. 마지막으로 남는 구슬은 어떻게 한 종류만 남게 된 것일까요? 우리의 최적해는 절대로 손해를 보지 않는데 말이죠.

그 이유는 한 원소가 너무 커서 나머지를 다 부딪혀도 남는 경우입니다.

max(S)>sum(S)max(S)max(S) \>> sum(S) - max(S)

최적해를 선택하더라도 손해는 안 봤지만, 어차피 모두 없앨 수 없는 거죠. 이런 경우는 max(S)(sum(S)max(S))max(S) - (sum(S) - max(S))가 정답입니다.

위의 경우만 아니라면 손해는 절대 보지 않습니다. 총 합이 홀수인 경우만 빼고요. 그땐 당연히 11이 남겠죠.

max(S)sum(S)max(S)max(S) \le sum(S) - max(S)

그런데 우리가 가장 큰 원소 두개씩 제거해나가는 과정에서 이 부등식이 깨지면 어떡하죠? 최적해를 따르면 이 부등식이 절대로 깨질일이 없음을 증명하겠습니다.

주어진 부등식을 이와 같이 바꾸겠습니다.
max(S)sum(S)2max(S) \le \displaystyle\frac{sum(S)}{2} 그리고 이걸 깨기 위해 최대한 노력하겠습니다.
일반적으로 구슬을 부딪히는 과정에서 max(S)max(S)11씩 줄어들고 sum(S)sum(S)11씩 줄어드는게 보통이지만, 무조건 그런 것은 아닙니다. max(S)max(S)가 여러 개 있다면 max(S)max(S)는 안줄어들 수도 있습니다. 이 점을 이용해서 최대한 부등식을 무너뜨리려고 노력해보겠습니다.

S=[x, x, x, x, ..., x, x, x](N=S)S = [x,\ x,\ x,\ x,\ ...,\ x,\ x,\ x](N = |S|)(NN은 홀수)
이러한 수열이 존재할 때, N1N-1(짝수)개를 서로 부딪혀서 없애면 max(S)max(S)는 변하지 않으면서 최대한 sum(S)sum(S)를 줄일 수 있습니다. 이러한 과정을 부등식으로 나타내면 다음과 같습니다.
xNx(N1)2xN(x1)+12x \le \displaystyle\frac{Nx-(N-1)}{2} \to x \le \displaystyle\frac{N(x-1)+1}{2}
우변을 최대한 작게 해야 하므로 xx11을 넣어 보겠습니다.
1121 \le \displaystyle\frac{1}{2}
성립하지 않습니다. 원소들이 모두 11인 경우는 사실 바로 처리할 수 있으니 넘어갑시다.
xx22를 넣어 보겠습니다.
2N+122 \le \displaystyle\frac{N+1}{2}
N3N \ge 3일 때, 언제나 성립함을 알 수 있습니다.
그런데 사실 N=1,2N = 1,2일 때는 너무나도 자명합니다. 그리고 우연인지 문제에서 의도한 것인지 모르겠지만 이 경우를 예외 처리하지 않고 아래와 같이 구현하더라도 맞습니다.

다음과 같이 해를 정리할 수 있습니다.
max(S)(sum(S)max(S)) (max(S)>sum(S)max(S))max(S) - (sum(S) - max(S))\ (max(S) > sum(S) - max(S))
sum(S) % 2 (max(S)sum(S)max(S))sum(S)\ \%\ 2\ (max(S) \le sum(S) - max(S))

3. 구현

사실 짝수이면 다 없앨 수 있고 홀수이면 1개가 남는다는 직관이 맞기는 한데 예제 입력 2에서 바로 반례를 줘버리니 정말 문제를 손으로 계속 풀어보고 규칙을 찾는 것이 더 중요한 아이디어성 문제인 것 같습니다. 증명하기도 진짜 어렵네요

import sys
input = sys.stdin.readline
N = int(input())
S = [int(input()) for i in range(N)]
m = max(S)
s = sum(S)
print(m - (s - m) if m > s - m else s % 2)

1) 시간 복잡도

문제 설명을 위해서 SS를 정렬한다고 했으나 사실 최대값만 필요한 것이므로 정렬 할 필요 없이 O(N)O(N)에 해결 할 수 있습니다.

profile
반갑습니다, 소통해요

0개의 댓글