POJ 3517 And Then There Was One (约瑟夫环问题)

经典的约瑟夫环问题嘛。有点小小的变形而已。给你N个人围成一个环(编号1~N),从第M个人开始,每隔K个人报一次数,报数的人离开该环。

求最后剩下的人的编号。

约瑟夫问题的数学递推解法:

(1)第一个被删除的数为 (m - 1) % n。

(2)假设第二轮的开始数字为k,那么这n - 1个数构成的约瑟夫环为k, k + 1, k + 2, k +3, .....,k - 3, k - 2。做一个简单的映射。

k         ----->  0

k+1    ------> 1

k+2    ------> 2

...

...

k-2    ------>  n-2

这是一个n -1个人的问题,如果能从n - 1个人问题的解推出 n 个人问题的解,从而得到一个递推公式,那么问题就解决了。假如我们已经知道了n -1个人时,最后胜利者的编号为x,利用映射关系逆推,就可以得出n个人时,胜利者的编号为 (x + k) % n。其中k等于m % n。代入(x + k) % n  <=>  (x + (m % n))%n <=> (x%n + (m%n)%n)%n
<=> (x%n+m%n)%n <=> (x+m)%n

(3)第二个被删除的数为(m - 1) % (n - 1)。

(4)假设第三轮的开始数字为o,那么这n - 2个数构成的约瑟夫环为o, o + 1, o + 2,......o - 3, o - 2.。继续做映射。

o         ----->  0

o+1    ------> 1

o+2    ------> 2

...

...

o-2     ------>  n-3

这是一个n - 2个人的问题。假设最后的胜利者为y,那么n -1个人时,胜利者为 (y + o) % (n -1 ),其中o等于m % (n -1 )。代入可得 (y+m) % (n-1)

要得到n - 1个人问题的解,只需得到n - 2个人问题的解,倒推下去。只有一个人时,胜利者就是编号0。下面给出递推式:

f [1] = 0;

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

约瑟夫问题详解请戳:http://blog.csdn.net/wuzhekai1985/article/details/6628491

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

有了以上递推式,还不赶快码之,AC之~

#include<cstdio>
#include<algorithm>
using namespace std;

int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&k,&m),m||k||n)
    {
        int s=0;
        for(int i=2;i<=n-1;i++)
            s=(s+k)%i;  //不用开数组哟。
        printf("%d\n",(s+m)%n+1);
    }
    return 0;
}

POJ 3517 And Then There Was One (约瑟夫环问题),布布扣,bubuko.com

时间: 2024-10-08 09:37:30

POJ 3517 And Then There Was One (约瑟夫环问题)的相关文章

poj 3517 And Then There Was One(约瑟夫环问题)

http://poj.org/problem?id=3517 讲解 n个人,编号为1~n,每次数到m的人出圈,最后一个出圈的人的编号. f[1] = 0; for(int i = 2; i <= n; i++) { f[i] = ( f[i-1] + m)%i; } printf("%d\n",f[n]+1); 这里第一次出圈的人的编号是m,然后从0开始数,每次数到k的人出圈,问最后出圈的人的编号. 注意递推顺序 #include <stdio.h> #include

Poj 3517 And Then There Was One(约瑟夫环变形)

简单说一下约瑟夫环:约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 想要求出最后剩下的那个人的在初始的时候的编号的话. f[1]=0; f[i]=(f[i-1]+m)%i;  (i>1) 可以推出剩下i个人内叫到m的时候的编号.注意这是逆推.推到最后初始的时候的情况 #include<stdio.h>

Poj 3517 And Then There Was One Joseph环问题

passport.baidu.com/?business&un=%E5%AD%A6%E5%A6%B9%E5%88%86%E5%AE%9C%E5%93%AA%E6%9C%89%E6%89%BE#0 passport.baidu.com/?business&un=%E5%A6%B9%E5%A6%B9%E9%B9%B0%E6%BD%AD%E5%93%AA%E6%9C%89%E6%89%BE#0 passport.baidu.com/?business&un=%E5%AD%A6%E5%A6

POJ 3517 And Then There Was One(约瑟夫环-递推or模拟)

POJ 3517 题目: n  k m 数字1到n成环,先叉数字m,往下数k个,直到最后只有一个数字,输出它. 链表模拟: #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<cmath> #include<vector> #incl

POJ 3517 And Then There Was One

题目链接:http://poj.org/problem?id=3517 And Then There Was One Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4843   Accepted: 2576 Description Let's play a stone removing game. Initially, n stones are arranged on a circle and numbered 1, -

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

POJ 3750,小孩报数问题,模拟约瑟夫问题

小孩报数问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9978   Accepted: 4649 Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序. Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩

poj 1012 &amp; hdu 1443 Joseph(约瑟夫环变形)

题目链接: POJ  1012: http://poj.org/problem?id=1012 HDU 1443: http://acm.hdu.edu.cn/showproblem.php?pid=1443 约瑟夫环(百度百科): http://baike.baidu.com/view/717633.htm?fr=aladdin Description The Joseph's problem is notoriously known. For those who are not famili

POJ 2886 Who Gets the Most Candies?(线段树&#183;约瑟夫环)

题意  n个人顺时针围成一圈玩约瑟夫游戏  每个人手上有一个数val[i]   开始第k个人出队  若val[k] < 0 下一个出队的为在剩余的人中向右数 -val[k]个人   val[k] > 0 时向左数val[k]个  第m出队的人可以得到m的约数个数个糖果  问得到最多糖果的人是谁 约瑟夫环问题  n比较大 直接模拟会超时   通过线段树可以让每次出队在O(logN)时间内完成  类似上一道插队的题  线段树维护对应区间还有多少个人没出队  那么当我们知道出队的人在剩余人中排第几个