简单约瑟夫环 系列(2) 【数学推导】

本文通过数学公式推导解决了约瑟夫环经典问题。首先为每个人分配编号,然后逐步减少人数并重新编号,最终形成递推公式 x=(x+k)%n。文中还提供了实现该算法的C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题简述 见  简单约瑟夫环系列(1)


下面用数学公式推导的方法,解决约瑟夫环经典问题。

第一步,这n个人我们给每一个人一个编号   0 ,1 ,2  ······  n-2,n-1

第二步,当第一轮游戏结束后,这n个人少就变成了n-1个人

第三步,将第一轮结束后剩下的人里面第一个报数的记为K,则这n-1个人 的编号为

                 k,k+1,k+2······n-2,n-1,0,1,2,······k-2(k-1也就是第一轮结束后出局的那个人)

第四步,也是最关键的一步,这n-1个人我们是不是也可以当成第一步那样重新来个编号,如下:

                k,k+1,k+2······n-2,n-1,0,1,2,······k-2

                 0 ,1 ,2  ······                        n-3,n-2(少了一个人所以到n-2)

            上面和下面一一对应

            于是,问题就转换到了n-1的情况,好了,发现了没,递推!

第五步  我们来推导数学公式。

              在四步的转换中k     - ->   0,那么当我们从反过来从n-1的情况推n的情况的时候,

              如果在n-1情况下X是最后胜出的人,那么在n的情况下   X+k就是最后胜出的人


由此,得出公式x=(x+k)%n


时间复杂度降低到了O(n)。


下面给出代码。



#include<iostream>
#include<stdio.h>

using namespace std;
int main(){
    
    int n,m;
    while(cin>>n>>m){
        int lastPeople=0;
        for(int i=1;i<=n;i++)
        {
            lastPeople=(lastPeople+m)%i;
        }
        cout<<lastPeople+1<<endl;
    }
    
    
    return 0;
}


转载于:https://my.oschina.net/zmixed/blog/638809

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值