People are standing in a circle waiting to be executed. Counting begins at a specified point in the circle and proceeds around the circle in a specified direction. starting from S, the next person is executed. The procedure is repeated with the remaining people, starting with the next person alive and going in the same direction, until only one person remains, and is freed.
The problem — given the Number of people , Starting point and Direction — is to choose the position in the initial circle to avoid execution. Example:
N=8
S=5
D=LEFT
1
8 2
7 3
6 4
5
5 kills 6
1
8 2
7 3
X 4
5
7 kills 8
1
X 2
7 3
X 4
5
1 kills 2
1
X X
7 3
X 4
5
3 kills 4
1
X X
7 3
X X
5
5 kills 7
1
X X
X 3
X X
5
1 kills 3
1
X X
X X
X X
5
5 kills 1
X
X X
X X
X X
5
5 is freed
Output
The winning position
Constraints
0<N<10000000000000 0<S<10000000000000
Solution
This problem is known as the Josephus Problem and has the following closed form solution:
\[J(n) = 2n - 2^{1+\lfloor\log_2(n)\rfloor} + 1\]
Instead of starting to count at position 1, we start at position \(s\), but need to wrap around if we overflow:
\[J_L(n) = 2n - 2^{1+\lfloor\log_2(n)\rfloor} + s \bmod n\]
But this is only true if we go in the left direction, when we go into the right direction, we need to reverse the result:
\[J_R(n) = -(2n - 2^{1+\lfloor\log_2(n)\rfloor}) + s \bmod n\]
Combining both formulas with D indicating the direction and handling the the offset for the modulo properly, the final \(O(1)\) solution is
const [n, s] = readline().split(' ').map(Number);
const d = readline();
let m = Math.floor(Math.log2(n));
let r = 2 * (n - 2 ** m);
if (d == 'RIGHT')
r = -r
console.log((r % n + s + n) % n);