约瑟夫问题两种解法

Posted fengwu2005

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫问题两种解法相关的知识,希望对你有一定的参考价值。

题目描述

有编号从1到N的N个小朋友在玩一种出圈的游戏。开始时N个小朋友围成一圈,编号为I+1的小朋友站在编号为I小朋友左边。编号为1的小朋友站在编号为N的小朋友左边。首先编号为1的小朋友开始报数,接着站在左边的小朋友顺序报数,直到数到某个数字M时就出圈。直到只剩下1个小朋友,则游戏完毕。

现在给定N,M,求N个小朋友的出圈顺序。

输入格式

唯一的一行包含两个整数N,M。(1<=N,M<=30000)

输出格式

唯一的一行包含N个整数,每两个整数中间用空格隔开,第I个整数表示第I个出圈的小朋友的编号

样例

样例输入

5 3

样例输出

3 1 5 2 4

简单来说,就是每次删除一个人,输出,继续循环一直输出到只剩最后一个人,输出。
如果要输出最后一个人,前面的输出直接省去就可以了
#include<iostream>
#include<cstdio>
using namespace std;
int main()

    bool m[30001];//存每个人是否还活着,false活着,true死了
    int a,b;//a个人,b出圈
    cin>>a>>b;
    for(int i=1;i<=a;++i)
        m[i]=false;//全部活着
    int c=0,d=0,e=0;//d为现在报的数
    do
    
        ++c;
        if(c==a+1)//如果到最后一个人后面,回到第一个,模拟环状
            c=1;
        if(m[c]==false)//如果这个人活着,报数
            ++d;
        if(d==b)
        
            d=0;//归零
            cout<<c<<" ";//要是只求最后一个人,省去
            m[c]=true;//这个人死了。。。。
            ++e;
        
    while(e!=a);//如果都死了,跳出

上面这个是简单版,时间复杂度为O(n2)

下面这个很烧脑,准备接住

约瑟夫问题2解决

 

题目描述

 

约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。请写一个程序,求出最后会剩下的人的编号。

输入格式

输入只有一行,为两个整数n,m(0<n,m<10^8)。

输出格式

只有一行,一个数,为剩下最后一个人的编号

样例

样例输入

6 5

样例输出

1
这个问题你们看到了数据规模很大n2绝对超时
当N的值有上百万,M的值为几万时,到最后虽然只剩2个人,也需要循环几万次(M的数量)才能确定2个人中下一个出列的序号。显然,在这个程序的执行过程中,很多步骤都是进行重复无用的循环。
现在有一个强大的数学规律
解析:
  其中,在约瑟夫环中,只是需要求出最后的一个出列者最初的序号,而不必要去模拟整个报数的过程。因此,为了追求效率,可以考虑从数学角度进行推算,找出规律然后再编写程序即可。
  我们从0开始循环(从零开始报数),到n-1,共n个人,第一个出圈的人是报数m-1的,所以他的编号是m-1或(m-1)%n(因为是从零开始,所以不用考虑+1问题)
  现在有n-1个人,从0循环到n-2(已经出圈的人的空位删掉),报数现在(删掉空位后)从(m-1)%n报0,1,2,3,4...。(m-1+
(m-1)%n)%(n-1)出圈,每一次都模现在的人数。
  实际上就是一层层的模
  现在我们逆推,假设现在只剩下1人,出圈的肯定是0号。
  
  设f=0,f是最后活的那个人在只剩下一个人的环中的编号
  现在进入两个人的环,报m-1的出圈,他就是当时的第m个,所以他在两个人的圈中的编号就是f+m,由于人数可能少于m,所以要用模,f=(f+m)%n n=2;
  然后进入三个人的圈,m-1继续出圈,他是第m个,在上一圈里,他是f,所以f=(f+m)%n n=3;
  以此类推,n=4,5,6,7,8......
  因为题中是从1开始报,所以在算出n个人的圈中,那个人的编号f后,要+1;
  
  程序很简单,一个循环就搞定;
  
#include<iostream>
using namespace std;
long long n,m,f;//在外面自动赋值为零
int main()

    cin>>n>>m;
    for(int i=2;i<=n;i++)//用i计算人数
        f=(f+m)%i;
    f++;
    cout<<f;

   小小见解,大神多多指教

 

以上是关于约瑟夫问题两种解法的主要内容,如果未能解决你的问题,请参考以下文章

约瑟夫问题特殊场景下的特殊解法

约瑟夫问题特殊场景下的特殊解法

小朋友学数据结构:约瑟夫环的链表解法数组解法和数学公式解法

约瑟夫环(猴子问题)最快解法

约瑟夫环(猴子问题)递归思路解法

Josephus环的四种解法(约瑟夫环)