[jobdu]孩子们的游戏(圆圈中最后剩下的数)

这道题就是典型的约瑟夫环问题。http://blog.csdn.net/wuzhekai1985/article/details/6628491 一开始想了一下用数组来做,就是模拟方法,同时记录一下是不是一个节点已经删除。然后看了一下,也很自然的可以用链表来做。但这样的复杂度都是O(m*n)。

如果不用模拟出其中的所有步骤,那么可以用数学方法来解,就是一个递推公式。f(n) = (f(n-1) + m) % n; f(1) = 1。

推导过程参加链接。但精华部分是,当n个数字删掉一个数后,就成为了n-1个数,假设知道n-1个数的剩下的编号x,就可以映射回原来n个数里面。“胜利者的编号为 (x + k) % n。其中k等于m % n。代入(x + k) % n  <=>  (x + (m % n))%n <=> (x%n + (m%n)%n)%n <=> (x%n+m%n)%n <=> (x+m)%n” 注意里面m%n%n = m%n。

#include <iostream>
using namespace std;
 
int main()
{
    int n;
    while (cin >> n)
    {
        if (n == 0) break;
        int m;
        cin >> m;
        int ans = 0;
        for (int i = 2; i <=n ; i++)
        {
                ans = (ans + m) % i;
        }
        cout << ans + 1<< endl;
    }
}

本来想把ans初始化为1的,但是算了一下不对。归根结底是%以后,结果是0到i-1;那么从0计数是最合理的,否则递推公式要全变。

原文地址:https://www.cnblogs.com/lautsie/p/3292727.html