首页 > 代码库 > 求圆圈中剩下的最后一个数字

求圆圈中剩下的最后一个数字

n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。

这个问题在wiki上叫约瑟夫斯问题。

一开始的序列是

S(n): n-1, 0, 1, 2, 3, ...., n -2 (一个环)

删除了第k=(m-1)%n个数,之后变成

S‘: n-1, 0, 1,2,...,k-1,k+1,...,n-2

S(n-1): n-2, 0, 1,2,3, ...,n-3 

将S(n-1)按照f(x)=(x+k+1)%n 进行映射可以得到S‘,也就是0->k+1, 1->k+2....

将S‘继续删除第k个数,以此类推,最后一个序列,也是可以通过S(1)来映射。

S‘ = (S(n-1) + (m-1)%n + 1) % n = (S(n-1) + m) % n.

那么对于每个序列的最后一个数, 也是满足这个映射。

f(n) = (f(n-1) + m) % n.

当n==1的时候,只有一个数,那么最后一个数肯定就是0,f(1) =0.

然后就可用动态规划去做了。

This approach has running time $O(n)$, but for small k and large n there is another approach. The second approach also uses dynamic programming but has running time $O(k\log n)$. It is based on considering killing k-th, 2k-th, ..., $(\lfloor n/k \rfloor k)$-th people as one step, then changing the numbering.

这里提到的第二种方法为什么会是$O(k\log n)$,没想明白? 把杀掉k-th, 2k-th, ..., $(\lfloor n/k \rfloor k)$-th当个步骤,所以总共需要k步。那也就是说,重新编号的开销是$\log n$.怎么做到的?