The CSES problem Josephus Problem I requires us to print the sequence of how people are chosen for n people and k = 2. I found an elegant solution to this here. Basically, the code is similar to this:
void J(int n)
{
int a = 1, b = 0;
while (n > 0)
{
for (int i = 2; i <= n; i += 2)
{
cout << a * i + b << ' ';
}
if (n & 1)
cout << a + b << ' ', b += a;
else
b -= a;
a <<= 1;
n >>= 1;
}
}
Can someone explain why it works?
I made a few changes to the code to illustrate how it works.
The first thing to note is that the variables
aandbare initialized to values that allow us to compute the positions of people who will be eliminated as we go around the circle (also using the iteratoriin theforloop). The initial values ofa = 1, b = 0are so we can eliminate every even numbered person on the first iteration.Next, every time through the
while(n)loop, half of the remaining people will be eliminated. Ifnis odd, we loop back to the beginning of the circle and also eliminate the person at the start of the current iteration.I think the tricky part here is how the values of
aandbchange in theifstatement. Ifnis odd we incrementbby the value ofa. Ifnis even we subtract the value ofafromb. Then we double the value ofato get ready for the next iteration around the circle. The values ofaandbare chosen to account for the gaps in the circle left by eliminating positions in the previous iterations.Finally, we divide
nby 2 before the next iteration, since there are half as many people left in the circle. Here's a sample run forn=19.Output: