约瑟夫环问题总结 poj3517,

原创 2018年03月31日 22:37:10

约瑟夫环:n个人报数,报到m的人出队,然后继续报,问最后出队人的编号。

最简单的方法链表模拟一下。而n很大时链表也无法在短时间得到结果。所以要找他的数学解法。

公式为f[i]=(f[i-1]+m)%i  (i从2循环到n)。

这个公式推导过程如下。

现将n个人重新编号为0~n-1

(1)   0,1,2,3,4,5,6,7.......n-1

取出第m个,即删掉编号m-1。

(2)   0,1,2,3,4,5,7,m-2,m,m+1......n-1

我们可以吧m左边的人移到n-1右边,即

(3)   m,m+1....n-1,n,n+1,n+m-2

我们发现序列又变成连续的序列。

然后序列重新从0到n-2编号

(4)   0,1,2,3,4,.......n-2

一直这样重复下去,最后只剩下一个0.

f[1]=0;

那么如何从f[1]推f[2]呢。


观察发现(4)式每个数+m即可得到(3)式。

(3)式模上当前人数n即可得到(2),

于是就推出了上面的公式:

f[i]=(f[i-1]+m)%i。


好了,有了这个前置技能,我们可以做题了,

首先第一题poj3517。

n个人吗,每次k步,起始位置为m,且m先被杀死。

1,2,3,4,5,6,7....m....n。

那么我们从第一步先杀死m,就相当于第一步是走了m步,而不是k步,所以

可以先递推前n-1项,然后处理f[n]时让它加上m,而不是加上k。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
ll f[101000];
int main()
{
	ll n,m,k;
	while(cin>>n>>k>>m)
	{
		if(n==0||m==0||k==0) break;
		f[1]=0;
		for(int i=2;i<n;i++)
		{
			f[i]=(f[i-1]+k)%i;
		}
		f[n]=(f[n-1]+m)%n;
		cout<<f[n]+1<<endl;
	}
	return 0;
}

poj1781,这题m固定是2,但n很大,所以要打表找规律。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;

int p[30];  
int main()  
{  
    for(int i = 0; i <= 27; i++)  
    {  
        p[i] = 1<<i;  
    } 
    char s[10];  
    int i;  
    while(~scanf("%s",s))  
    {  
        if(strcmp(s,"00e0") == 0) break;  
        int n;  
        n=(s[0]-'0')*10+s[1]-'0';
        for(i=1;i<=s[3]-'0';i++)  
        n=n*10;
        for(i=0;i<=27;i++)  
            if(p[i]>=n)  
                break;  
        if(p[i] == n)  
            printf("1\n");  
        else  
            printf("%d\n",n-(p[i]-n-1));  
    }  
    return 0;  
}


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37632935/article/details/79773753

障碍用户类型及他们可能遇到的问题 -- 刘彪

-
  • 1970年01月01日 08:00

约瑟夫环问题

约瑟夫环问题 问题描述:n个人(编号1~n),从1开始报数,报到m的退出,剩下的人继续从1开始报数。求胜利者的编号。数学解法复杂度:O(n)。 无论是用链表实现还是用数组实现都有一个共同点:要模拟整个...
  • quentain
  • quentain
  • 2015-11-28 09:12:36
  • 1527

算法理解——约瑟夫环

前几天去优酷笔试,有一个约瑟夫环的问题,当时由于时间比较紧张加上长久不写算法,当时没写出来。后来回来后想了一下,其实用java写非常简单,这里面利用了java提供的list,与传统的C语言写法相比,难...
  • jinyongqing
  • jinyongqing
  • 2013-09-27 16:55:14
  • 1366

约瑟夫环问题递归解法的一点理解

约瑟夫环递归解法代码的一点理解。 约瑟夫生者死者游戏 约瑟夫游戏的大意:30个游客同乘一条船,因为严重超载, 加上风浪大作,危险万分。因此船长告诉乘客,只有将全船 一半的旅客投入海中,其余人才能幸...
  • yanweibujian
  • yanweibujian
  • 2016-03-13 11:32:58
  • 2974

约瑟夫环的问题1

n个人做成一圈,顺时针由1开始给他们编号,然后由第一个人进行报数,数到m的人出局,接着下一个人又从1开始报数,只剩最后一个人的时候求这个人的编号特例:当m = 2的时候① n = 2^k如果只有2个人...
  • qq_31837563
  • qq_31837563
  • 2018-04-17 20:34:06
  • 57

约瑟夫环问题-(转载)

转载自https://blog.csdn.net/tingyun_say/article/details/523438971.首先,我们先来了解一下什么是约瑟夫环问题:讲一个比较有意思的故事:约瑟夫是...
  • Z_sea
  • Z_sea
  • 2018-04-18 17:10:01
  • 10

约瑟夫环

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,4...
  • Rae8023
  • Rae8023
  • 2018-04-02 18:09:00
  • 11

约瑟夫环乘客问题

        30个乘客同乘一艘船,因为严重超载,加上风高浪大,危险万分,因此船长告诉乘客,只有将15名乘客投入海中,其他人才能幸免于难。大家决定30个人围成一圈,从第一个人数起,依次报数,数到第九...
  • qq_41822235
  • qq_41822235
  • 2018-04-16 10:38:50
  • 10

模拟 - 约瑟夫环问题及其变式

约瑟夫斯问题   约瑟夫斯问题(有时也称为约瑟夫斯置换),是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。 有 n  个囚犯站成一个圆圈,准备处决...
  • qq_33677789
  • qq_33677789
  • 2016-06-12 19:51:33
  • 272

14、约瑟夫环

已知n个人围坐在一张圆桌周围,从编号为1的人开始报数,数到m的那个人出列。下一个人从1开始报数,数到m的人继续出列,以此类推直至全部人出列。求出列顺序? 解决方案: 1、最简单明了的办法就是用循环...
  • llianlianpay
  • llianlianpay
  • 2018-04-17 10:33:37
  • 7
收藏助手
不良信息举报
您举报文章:约瑟夫环问题总结 poj3517,
举报原因:
原因补充:

(最多只允许输入30个字)