poj 3517

最简单的约瑟夫环,虽然感觉永远不会考约瑟夫环,但数学正好刷到这部分,跳过去的话很难过

直接粘别人分析了

约瑟夫问题:

用数学方法解的时候需要注意应当从0开始编号,因为取余会等到0解。

实质是一个递推,n个人中最终存活下来的序号与n-1个人中存活的人的序号有一个递推关系式。

分析:

假设除去第k个人。

0, 1, 2, 3, ..., k-2, k-1, k, ..., n-1  //original sequence (1)

0, 1, 2, 3, ..., k-2,      , k, ..., n-1  //get rid of kth person (2)

k, k+1, ..., n-1,    0,    1,        ..., k-2  //rearrange the sequence (3)

0, 1,     ..., n-k-1, n-k, n-k+1, ..., n-2  //the n-1 person (4)

我们假设f(n)的值为n个人中最后存活的人的序号,则

注意到(2)式(3)式(4)式其实是同一个序列。//这个很重要啊,要想清楚,这三个是同一个式子

注意(1)式和(4)式,是同一个问题,不同的仅仅是人数。

假设我们已知f(n-1),即(4)式中最后剩下的人的序号,则(3)式所对应的序号,就是f(n),即(1)式n个人中最后存活的序号。

而从(3)(4)式中我们不难发现有这样一个递推式:

f(n) = (f(n-1) + k) % n

显然,f(1) = 0。

于是递推得f(n)

因为是从m开始,所以递推的最后要单独列出来

普通的约瑟夫是从0开始

 1 #include <stdio.h>
 2
 3 int main()
 4 {
 5     int n, k, m, i, x;
 6     while (scanf("%d%d%d", &n, &k, &m) != EOF) {
 7     if (n==0 && k==0 && m==0) break;
 8     x = 0;
 9     for (i=2; i!=n; ++i)
10         x = (x + k) % i;
11     x = (x + m) % i + 1;
12     printf("%d\n", x);
13     }
14     return 0;
15 }
时间: 2024-12-27 16:37:28

poj 3517的相关文章

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    

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(约瑟夫环-递推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 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 Joseph核心问题

基本上纯Joseph核心问题,只是第一步多一件.m. 然后你就可以用获得的递推公式: Win(n) 代表n当个人的中奖号码, 然后,Win(n)必须相等Win(n-1).当一个人将在下一次删除队列. 下一个出队列的人是谁呢? 假设模是mod的话,那么下一个出队号码计算为: Lose(n) = mod % n; if (Lose(n) == 0) Lose(n) = n; 这样得到公式: Win(n) - Lose(n)  = Win(n-1); Win(n) = Win(n-1) + Lose(

poj 3517(约瑟夫环问题)

And Then There Was One Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4873   Accepted: 2598 Description Let’s play a stone removing game. Initially, n stones are arranged on a circle and numbered 1, …, n clockwise (Figure 1). You are al

约瑟夫问题合集

swustoj 142 猴子报数(0142)Time limit(ms): 1000Memory limit(kb): 65535Submission: 1338Accepted: 830 问题描述:n个猴子围坐一圈并按照顺时针方向从1到n编号,从第s个猴子开始进行1到m的报数,报数到第m的猴子退出报数,从紧挨它的下一个猴子重新开始1到m的报数,如此进行下去知道所有的猴子都退出为止.求给出这n个猴子的退出的顺序表. 输入:有做组测试数据.每一组数据有两行,第一行输入n(表示猴子的总数最多为100