Baekjoon Online Judge 23575

December 30, 2021

23575 Squid Game

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

물통 1, 2, 3에 각각 물이 X,Y,ZX, Y, Z리터 들어있다. xyx \le y에 대해, xx리터의 물이 들어있는 물통 AAyy리터의 물이 들어있는 물통 BB을 선택하여, 물통 AA2x2x리터, 물통 BB(yx)(y - x)리터의 물이 남도록 물통 BB에서 물통 AA로 물을 붓는 동작을 할 수 있다. 처음 물의 양 1XYZ1091 \le X \le Y \le Z \le 10^9가 주어졌을 때, 1000번 이내의 동작으로 한 물통을 완전히 비우도록 하는 동작을 순서대로 출력하라. 물통 BB에서 물통 AA로 물을 붓는 동작을 BAB\: A와 같은 꼴로, 각 동작마다 개행하여 출력하면 된다.

힌트

개인적으로는 상세한 풀이를 참고하지 않고 풀어볼 수 있다면 충분히 재미있는 문제가 될 것이라고 생각하여 이 문제에 대해 비슷한 감상을 갖는 이를 위해 문단을 추가하였습니다.

힌트 1: 제시될 풀이의 방향 동작을 통해 물통에 든 물의 최솟값을 줄일 방법에 대해 생각할 것이다.
힌트 2: 힌트 1의 상세 최대 30번 정도의 동작을 통해 최솟값을 2배 줄일 방법이 존재한다고 가정하면, $10^9 < 2^{30}$이므로, 대략 30번 정도의 이러한 동작 묶음을 통해 최솟값을 감소시켜 0으로 만들 수 있다.
힌트 3: 풀이 요약 물을 붓는 동작을 사용하여 나눗셈을 구현하였다. 최대 30번 정도의 동작을 통해 $x \le y$에 대해 $x, y$리터의 물이 담긴 물통으로부터 $y % x$리터 또는 $(k * x - y) % x$리터의 물이 남은 물통을 만들 수 있다 ($k$는 $k * x - y$를 음이 아닌 정수로 만드는 임의의 수이다). $x, y$에 따라 둘 중 하나를 선택하여 최솟값이 2배 줄일 수 있다. $10^9 < 2^{30}$이므로, 대략 30번 정도의 이러한 동작 묶음을 통해 최솟값을 감소시켜 0으로 만들 수 있다.

풀이

동작 묶음 구성

물통에 든 물의 양이 각각 x,y,zx, y, z리터라고 하자. 물통 1, 2, 3에 각각 물이 x,y,zx, y, z리터 들었을 때, xyzx \le y \le z이도록 물통의 번호를 잘 바꾸자.

우선 zz를 크게 만들고 나서 시작하려고 한다. x+y<zx + y < z가 성립하지 않는다면 물통 3에서 물통 2로 물을 부을 것이다. 각 물통에는 x,2y,zyx, 2y, z - y만큼의 물이 남는다. y>0y > 0인 경우 x+z<3yx + z < 3y가 성립하는데, 아니라면 x+z3yx + z \ge 3y이고 x+yzx + y \ge z이므로 02y0 \ge 2y이고 이는 모순이다. 이때 x+(zy)<2yx + (z - y) < 2y이므로, 물통들의 번호를 적절히 바꾸고 새로운 값에 변수를 다시 붙여, 물통 1, 2, 3에 각각 물이 x,y,zx, y, z리터 들었고, xyzx \le y \le zx+y<zx + y < z를 만족한다고 가정하자.

다음으로 물통에 남은 물의 양 중 최솟값이 ymodxy \bmod x리터 또는 x(ymodx)x - (y \bmod x)리터 이하가 되도록 만들 것이다. y=qx+ry = qx + r, 0r<x0 \le r < x라고 하자. xyx \le y이므로 q1q \ge 1이다. q=1q = 1인 경우를 예시로 들어 어떤 전략을 취하여야 할지 생각하여 볼 것이다.

  • xy<32xx \le y < \frac{3}{2} x인 경우, ymodxy \bmod x12x\frac{1}{2}x보다 작거나 같다. 이 경우에는 물통 2에서 물통 1로 물을 부었을 때 물통 2에 물이 ymodxy \bmod x리터 남는다.
  • 32xy<2x\frac{3}{2} x \le y < 2x인 경우, x(ymodx)x - (y \bmod x)12x\frac{1}{2}x보다 작거나 같다. 이 경우에는 물통 3에서 물통 1로 물을 부은 후, 물통 1에서 물통 2로 물을 부었을 때 물통 1에 물이 2xy=x(ymodx)2x - y = x - (y \bmod x)리터 남는다.

각 경우는 ymodxy \bmod x12x\frac{1}{2} x를 비교하여 구별할 수 있다. q>1q > 1인 경우에 비슷한 결과를 만들 수 있는지 탐색하자.

우선, r=ymodxr = y \bmod x12x\frac{1}{2}x보다 작거나 같다고 가정하자.

  • qmod2=0q \bmod 2 = 0일 때, 물통 3에서 물통 1으로 물을 부을 것이다. 물통 1, 2에 각각 물이 2x,y2x, y리터 남는데, y=q/22x+ry = q/2 \cdot 2x + r이다.
  • qmod2=1q \bmod 2 = 1일 때, 물통 2에서 물통 1으로 물을 부을 것이다. 물통 1, 2에 각각 물이 2x,yx2x, y - x리터 남는데, yx=(q1)/22x+ry - x = (q - 1)/2 \cdot 2x + r이다.

위 과정 이후 qqq/2q/2를 대입하고, q>1q > 1인 동안 위 과정을 반복한다. 물통 3에 물이 충분히 있으므로 위 과정은 동작한다. q=1q = 1이 되었을 때 전술한 동작을 통해 물통 2에 물을 rr리터 남길 수 있다.

rr12x\frac{1}{2}x보다 크거나 같다고 가정하자. 새로운 과정을 소개하기 전에, 위 과정을 분석하여 보자. 위 과정은 물통 2에 r=yqxr = y - qx리터를 남기게 된다. 이 과정은 직관적으로는 다음과 같이 이해할 수 있다:

  • 두 물통의 물 차이가 yqxy - qx리터가 될 때까지 물을 잘 옮긴다.
  • 마지막 동작을 통해 차이를 실현한다.

그러니 이번에는 다음과 같이 과정을 설계할 수 있을 것이다:

  • 두 물통의 물 차이가 (q+1)xy(q + 1) x - y리터가 될 때까지 물을 잘 옮긴다.
  • 마지막 동작을 통해 차이를 실현한다.

따라서 qq 대신 q+1q + 1를 초기값으로 주어 위 과정을 반복하고, 마지막 동작에서 물통 1에서 물통 2로 물을 부어 물통 1에 (q+1)xy=xr(q + 1) x - y = x - r리터를 남길 수 있다.

위 동작 묶음을 수행하였을 때, 남아있는 물의 양 중 최솟값이 기존 최솟값의 12\frac{1}{2}보다 작거나 같게 된다. 최솟값을 줄이는 위의 과정을 동작 묶음이라고 부르자. 동작 묶음이 수행될 때마다 물의 양의 최솟값이 줄어들게 되므로, 동작 묶음을 유한하게 많이 사용하여 물통 하나를 비울 수 있다. 따라서 위 동작 묶음에 따라 동작을 나열하는 해답의 정당성이 증명된다.

분석: 동작 횟수

그러나 이 문제는 단지 동작을 나열할 뿐이 아니라, 동작의 횟수가 1000회로 제한되어 있다. 따라서 위 풀이를 검증하기 위해서는 동작의 정당성 뿐만 아니라 횟수에 대해서도 추가적인 분석이 필요하다.

풀이에 서술된 동작 묶음에 동작이 최대 몇 개 포함되었는지 분석하여 보자.

  • x+y<zx + y < z를 가정하기 위해 최대 1회
  • q=yx109<230q = \left\lfloor \frac{y}{x} \right\rfloor \le 10^9 < 2^{30}. 1+log2q301 + \lfloor \log_2 q \rfloor \le 30회.

따라서 각 동작 묶음 당 최대 31회의 동작을 수행한다. 초기 최솟값은 109<23010^9 < 2^{30}이므로, 최솟값을 절반씩 줄이는 경우 동작 묶음을 최대 31회 사용한다. 따라서 위 풀이는 동작을 최대 3131<100031 \cdot 31 < 1000회 사용한다. 이는 문제의 조건과 일치한다.

대부분의 경우 1000회보다 훨씬 적은 횟수로 해답이 나올 것 같지만 적당한 분석을 수행할 수 없었다.

계산 복잡도

시간이 아주 오래 걸리지는 않는다. 각 수행마다 x+y<zx + y < z, qmod2q \bmod 2 정도만 살피면 되기 때문이다. 시간 0ms으로 동작하는 해 또한 구성할 수 있다.

문제의 조건이 1XYZN1 \le X \le Y \le Z \le N으로 주어졌을 때, 위 분석을 사용하면 답의 크기는 O((logN)2)\mathcal{O}((\log N)^2) 정도일 것으로 추측한다.