约瑟夫环问题【数学递推】【优化版】

约瑟夫环问题

问题:n个人编号1~n,报数报到m的出队,问最后一个人是谁(队列成环)

数学递推:复杂度O(n)

Josephus(int n,int m)
{
    int s = 0;
    for (int i = 2; i <= n; i++)
    {
        s = (s + m) % i;
    }
    return s;
}

——稍加优化——
注意:做ACM题时,经常遇到取模操作, 取模运算是算术操作中中最慢的(在当前的计算机硬件中基本都是这样)。
1 对2的幂取模(2^k),实际等同于和(2^k – 1)进行“位与”操作
例如对8取模,因为计算机内部是二进制表示,所以可以对二进制位进行位与操作。

2 经常有一些递推式,是加和后求模关系,这时可以利用有限范围的特性, 将求模转换为加减法

摘自取模速度优化

所以从这一点入手,可以优化为

Josephus(int n,int m)
{
    int s = 0;
    for (int i = 2; i <= n; i++)
    {
        if (m >= i) s = s + m % i;
        else s = s + m;
        if (s >= i) s -= i;
    }
    return s;
}

——更加优化——
// 这里其实并不是很懂,附上代码

int Josephus(int n,int m, int k)  //人数、步长、起始报数位置
{
    if (m == 1)
    {
        k = k == 1? n : (k + n - 1) % n;
    }
    else
    {
        for (int i = 1; i <= n; i++)
        {
            if (k + m < i)
            {
                int x = (i - k + 1) / (m - 1) - 1;
                if (i + x < n)
                {
                    i = i + x;
                    k = (k + m * x);
                }
                else
                {
                    k = k + m * (n - i);
                    i = n;
                }
            }
            k = (k + m - 1) % i + 1;
        }
    }
    return k;
}
    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/loy_184548/article/details/52004872
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞