很早就看到过这个题目了,当时都是用循环链表做的,这样可以逐次节省内存。
没想到,这却可以用几行代码用数学方法轻松实现~
参考了学长Alex4814的博客,原来借助抽象函数f(n)可以解释得更清楚。
n个人编号:0,1,2,……,k-2,k-1,k,……,n-1;//包含0的话刚好是n的完全剩余系,更方便讨论
抽去第k人:0,1,2,……,k-2,k,……,n-1;//编号为k-1的是第k人
只剩下了n-1个人,相当于一个环减去了一节,重新安置头和尾:
k,k+1,……,n-1,0,1,2,……,k-2;(x+k)%n
n-1个人编号:0,1,2,……,k-1,k,k+1,……,n-2; x
于是问题化简到了n-1个人的求解问题。并且这两个数列除了k-1有一一对应的关系
设f(n)是n个人里幸存者的编号,那么:f(n)=(f(n-1)+k)%n
并且显然,有:f(1)=0
依次可以得到1,2,3,……,n人对应的幸存者编号;
题目给的编号是从1开始的,平移即可。
#include <stdio.h>
int main()
{
int n, m, k;
while(~scanf("%d%d%d", &n, &m, &k))
{
if(!n && !m && !k)
break;
int x = 0, y;
for(int i = 2;i < n;i++)
x = (m+x)%i;
printf("%d\n", (x+k)%n+1);
}
return 0;
}