Boj 11025) 요세푸스 문제 3
문제
설명
\[f(n, k) = (f(n-1, k) + k - 1 \mod n) + 1\]
요세푸스 수열의 마지막 항에 대한 점화식은 위와 같다.
이는 일대일 대응되는 수열 간의 변환 식을 유추하므로써 구할 수 있다. 다음을 살펴보자.
(n, k) 일때
4 5 6 7 1 2 // (7, 3) 에서 1회 수행 시 큐에 남는 수
1 2 3 4 5 6 // (6, 3) 에서 0회 수행 시 큐에 남는 수
4 5 6 1 2 // (6, 3) 에서 1회 수행시 큐에 남는 수
1 2 3 4 5 // (5, 3) 에서 0회 수행시 큐에 남는 수
...
1 // (2, 3) 에서 1 회 수행시 큐에 남는 수
1 // (1, 3) 에서 0 회 수행시 큐에 남는 수
- 1회 수행한 요세푸스 수열 \(j(n, k)_1\) 은 \(j(n-1, k)_0\) 과 일대일 대응이 성립한다.
- 두 수열 간의 변환은 k 를 더하고 모듈로 연산을 하는 간단한 식으로 정의할 수 있다.
- 그러므로 요세푸스 수열 \(j(1, k)_0\) 부터 변환을 반복하면 \(j(n, k)_0\) 의 마지막 항이 된다.
자세한 것은 위키 를 살펴보자. 의외로 나무위키 에도 잘 설명되어 있다.
시간 복잡도
O(\(\mathrm{N}\))
코드
큰 N 에 대한 joseph
조금만 더 생각하면 일대일 대응하는 수열을 적절히 선택해 변환식을 유추할 수 있으면 다양한 점화식을 만들어 낼 수 있다는 걸 알 수 있다. 이를 활용한 점화식 중 하나가 n
에 비해 k
가 매우 작은 경우이다. 이는 SO를 보면 페이스북 해커톤의 기출문제로도 나왔다고 한다. 비슷한 문제가 Boj 에 있으며 이것을 풀어보자.
1 2 3 4 5 6 7 8 9 10 // (10, 3) 에서 0 회 수행
1 2 4 5 7 8 10 // (10, 3) 에서 3 회 수행
2 3 4 5 6 7 1 // (7, 3) 에서 0 회 수행
1 2 3 4 5 6 7 8 // (8, 3) 에서 0 회 수행
1 2 4 5 7 8 // (8, 3) 에서 2 회 수행
3 4 5 6 1 2 // (6, 3) 에서 0 회 수행
n 이 매우 크기때문에 한번에 1개씩 지우는게 아니라 한줄을 훑으면서 지웠다. 그러면 위처럼 나타낼 수 있다.
이에 대한 변환식은 다양한 접근으로 구할 수 있다. 나는 0회 수행한 수열에서 기본적으로 n / k * k
를 더하고, 특정 간격마다 일정한 간격으로 커지는 수를 더하면 된다는 것을 이용하였다. 이를 코드로 나타내면 다음과 같다.
시간복잡도
위키 등을 보면 O(\(k\log_{\mathrm{N}}\)) 가 된다고 한다.
- 내가 계산하기엔 O(\(\log_{k+1}{N}\)) 이 나오던데 이상할 따름이다.나는 \(n_{m} = n_{m+1} - n_{m+1}/k\) 를 풀어서 \(n_{m+1} = \cfrac{k-1}{k} n_{m}\) 의 점화식을 구했다. 그리고 이를 변형해 \((\cfrac{k-1}{k})^N = 1\) 을 만족하는 \(N\) 을 구하면 될거라 생각했는데 뭔가 다른가보다.
댓글남기기