解释约瑟夫循环,谢谢

#include<stdio.h>
void main()
{
int n,m,i,s=0;
scanf("%d,%d",&n,&m);
for(i=2;i<=n;i++)
s=(s+m)%i;
printf ("The winner is %d\n", s+1);
}

百度百科里有,不过抱歉,我没看太明白...

Josephus(约瑟夫)问题的数学方法
  无论是用链表实现还是用数组实现都有一个共同点:要模拟整个游戏过程,不仅程序写起来比较烦,而且时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,几乎是没有办法在短时间内出结果的。我们注意到原问题仅仅是要求出最后的胜利者的序号,而不是要读者模拟整个过程。因此如果要追求效率,就要打破常规,实施一点数学策略。
  为了讨论方便,先把问题稍微改变一下,并不影响原意:
  问题描述:n个人(编号0~(n-1)),从0开始报数,报到m-1的退出
  ,剩下的人继续从0开始报数。求胜利者的编号。
  我们知道第一个人(编号一定是(m-1)%n) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始):
  k k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2
  并且从k开始报0。
  现在我们把他们的编号做一下转换:
  k --> 0
  k+1 --> 1
  k+2 --> 2
  ...
  ...
  k-3 --> n-3
  k-2 --> n-2
  序列1: 0, 1, 2, 3 … n-2, n-1
  序列2: 0, 1, 2, 3 … k-1, k+1, …, n-2, n-1
  序列3: k, k+1, k+2, k+3, …, n-2, n-1, 1, 2, 3,…, k-2,
  序列4:0, 1, 2, 3 …, 5, 6, 7, 8, …, n-3, n-2
  变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变回去的公式很简单,相信大家都可以推出来:
  ∵ k=m%n;
  ∴ x' = x+k = x+ m%n ; 而 x+ m%n 可能大于n
  ∴x'= (x+ m%n)%n = (x+m)%n
  得到 x‘=(x+m)%n
  如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就行了。(n-2)个人的解呢?当然是先求(n-3)的情况 ---- 这显然就是一个倒推问题!好了,思路出来了,下面写递推公式:
  令f表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n].
  递推公式:
  f[1]=0;
  f[i]=(f[i-1]+m)%i; (i>1)
  有了这个公式,我们要做的就是从1-n顺序算出f的数值,最后结果是f[n]。我们输出f[n]由于是逐级递推,不需要保存每个,程序也是异常简单:(注意编号是0 -- n-1)
  #include <stdio.h>
  int main(void)
  {
  int n, m, i, s=0;
  printf ("N M = ");
  scanf("%d%d", &n, &m);
  for (i=2; i<=n; i++)
  s=(s+m)%i;
  printf ("The winner is %d\n", s);
  return 0 ;
  }
温馨提示:内容为网友见解,仅供参考
无其他回答

我想问一下约瑟夫问题的递推公式为什么是 s = (s + m) % i;谢谢
首先上题目,有n个人围成一圈,报数从1到m依次循环报数,报到m的就退出(死)。现在我们来看递推,由于为了方便表示(s+m)%i=0的情况,我们让第一人的编号为0,(从一开始也可以)。既然你问递推,那步骤就不说了,只说这个公式吧 让获胜者的编号为0(最后一个人只有他了当然是0)f(i)表示...

谁帮我解释一下约瑟夫问题,谢谢,程序如下
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。我们知道第一个人(编号一定是m%n-1) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始):k k+1 k+2 ... n-2, n-1, 0, 1, 2, ......

约瑟夫问题:M个人围成一圈,从第一个人开始依次从1到N循环报数,每当报数...
设有n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数 (用数学方法解的时候需要注意应当从0开始编号,因为取余会取到0解。)实质是一个递推,n个人中最终留下来的序号与n-1个人中留下来的人的序号有一个递推关系式。假设除去第k个人,则 0, 1, 2, 3...

...这是约瑟夫环的程序, 希望能给出具体的解释,谢谢!!!急需急需...
while (n) \/\/只有n不为0,也就是队列还有人没出队就继续循环 { while (i != m) \/\/i为报号数,如果报号还没到m,则继续报号 { q = p; \/\/迭代过程,p为当前节点,q为当前节点的前一个节点 p = p->next;i++;} printf("%-3d",p->data); \/\/循环出来表示报号到这...

约瑟夫问题41个人围成一圈由第一个人开始数到第三个就死一直循环找出不...
int total =41; \/\/总人数 j=0;int a[total];for(i=0;i<41;i++){a[i]=1;} \/\/数组a初始化,1表示活着。。。i=0;j=1;for(;;) \/\/循环开始 { if(a[i]==1){ \/\/只有这个人活着我们才会去判断是不是数到3了,如果死了,就应该跳过 if(j==3){ \/\/到这个人...

C++编程:约瑟夫环问题。
\/\/ 基本的约瑟夫构造函数 JosephCircle(int N,int S,int D);\/\/ 发展的约瑟夫构造函数 JosephCircle(int N,int S,int M,int password[]);\/\/ 输出约瑟夫环 void print();\/\/ 开始处决犯人 void start();private:\/\/ 约瑟夫环的头指针 struct Prisoner * head;\/\/ 第一个被处决的犯人的节点指针...

约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈...
q->next=head;\/\/建立循环链表 pri=q;p=head;\/\/从head开始循环 people=0;passord=1;\/\/出去了几个人、记录的密码数 while(people<n){ pri=pri->next;p=p->next;passord++;if(passord==m){ printf("%-4d",p->data);node *temp;temp=p;pri->next=p->next;p=p->next;free(temp...

数学高手进!!1000围成圈1至10循环报数,报道10的推出,最后剩谁?
你提出的问题是计算机算法领域很著名的一个问题——约瑟夫问题,它的一般形式是:N个人1-N编号,从1循环报数报到M的人退出,最后退出的那个人编号是多少?设最后一个退出的人编号J(N,M),据我所知还没人能把J(N,M)写成N,M的解析函数式。但是有一些可供手工和编程计算J(N,M)的算法,下面详细说...

你好可以帮忙给新手写一个约瑟夫出圈的代码吗?最好帮忙给加上注释,谢...
而continue,意思是“(中断后)继续”,所以引申为“从continue处结束本次循环,中止本次循环,不执行本次循环中continue之后的语句,但(中断后)没有跳出该循环控制体,继续执行本次循环之后的循环”两者的共同点是:都不会执行本次循环中break\/continue之后的语句;两者的不同点是:continue是中断之后...

约瑟夫问题
约瑟夫问题并不难,但求解的方法很多;题目的变化形式也很多。这里给出一种实现方法。 题目中30个人围成一圈,因而启发我们用一个循环的链来表示。可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个人开始对...

相似回答
大家正在搜