约瑟夫环问题

/**
    问题描述:已知n个人(编号1,2...n)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;
               他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,求最后出列的人的编号。
               (以下代码是默认k = 1)

    (1) 循环链表的方法时间复杂度为O(n*m).
    (2) 一个时间复杂度为O(n)的数学方法,思路如下:
           假设当前剩下i个人(i<=n),显然这一轮m要挂(因为总是从1开始数).经过这一轮,
           剩下的人是:1 2 3...m-1 m+1...i, 我们将从m+1开始的数映射成1,则m+2对应2, n对应i-m,
           1对应成i-m+1, m-1对应i-1,那么现在的问题变成了已知 i-1个人进行循环报数m,求出去的人的序号。
           假设已经求出了i-1个人循环报数下最后一个出去的人的序号x0,那么它在n个人中的序号 x1 = (x0+m-1)%n + 1,
           最初的 x0=1 ,反复迭代 x0和x1可以求出.
**/


#include <stdio.h>

int main()
{
    int n, m, s, i;

    scanf("%d %d", &n, &m);
    s = 1; //初值为1
    for (i=2; i<=n; i++)
    {
        s = (s+m)%i;
        if (s == 0) s = i;
          //这两个语句也可以用s = (s+m-1)%i + 1;来代替
    }
    printf("answer = %d/n", s);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值