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 also given two numbers k and m. From this state, remove stones one by one following the rules explained below, until only one remains. In step 1, remove stone m. In step 2, locate the k-th next stone clockwise from m and remove it. In subsequent steps, start from the slot of the stone removed in the last step, make k hops clockwise on the remaining stones and remove the one you reach. In other words, skip (k − 1) remaining stones clockwise and remove the next one. Repeat this until only one stone is left and answer its number. For example, the answer for the case n = 8, k = 5, m = 3 is 1, as shown in Figure 1.


Initial state

Step 1

Step 2

Step 3

Step 4

Step 5

Step 6

Step 7

Final state
 

Figure 1: An example game

Initial state: Eight stones are arranged on a circle.

Step 1: Stone 3 is removed since m = 3.

Step 2: You start from the slot that was occupied by stone 3. You skip four stones 4, 5, 6 and 7 (since k = 5), and remove the next one, which is 8.

Step 3:
You skip stones 1, 2, 4 and 5, and thus remove 6. Note that you only
count stones that are still on the circle and ignore those already
removed. Stone 3 is ignored in this case.

Steps 4–7:
You continue until only one stone is left. Notice that in later steps
when only a few stones remain, the same stone may be skipped multiple
times. For example, stones 1 and 4 are skipped twice in step 7.

Final State: Finally, only one stone, 1, is on the circle. This is the final state, so the answer is 1.

Input

The input consists of multiple datasets each of which is formatted as follows.

n k m

The
last dataset is followed by a line containing three zeros. Numbers in a
line are separated by a single space. A dataset satisfies the following
conditions.

2 ≤ n ≤ 10000, 1 ≤ k ≤ 10000, 1 ≤ mn

The number of datasets is less than 100.

Output

For
each dataset, output a line containing the stone number left in the
final state. No extra characters such as spaces should appear in the
output.

Sample Input

8 5 3
100 9999 98
10000 10000 10000
0 0 0

Sample Output

1
93
2019

Source

Japan 2007

题目描述 : n个数排成一圈,第一次删除,以后每数k个数删除一次。求最后一次被删除的数。

假设数字标号为0,1,2,3,,,n-1,。第一次删除的数是k,那么还剩0,1,2,3,,,k-1,k+1,k+2,,,,n-1;

那么问题就转化为求这n-1个数,最后一次被删除的数?,最优子结构,定义状态f[n]代表对n个数进行操作,最后一次被删除的数。

我们需要重新对这n-1个数重新编号,k+1,k+2,k+3,,,n-1,0,1,2,3,4, ,,k-1,重新编号为,0,1,2,3,4,5,,,,n-1.

f[n]与f[n-1]有什么关系呢?f[n]=(f[n-1]+k)%n;因为只是重新编号,所以我们只需将n-1个数所求的最后一个数的序号转化为n个数要求的最后一个数的序号.

题目要求第一次删除的是m,那么我们考虑-k+1,开始数k个数,那么第一次删除的就是0号元素,而且如果0号元素是m的话,那么f[n]号元素就为f[n]+m.

int answer=(m-k+1+f[n])%n;

if(answer<=0)

answer+=n;

不能写成(answer+n)%n,因为answer==0,n%n==0.

#include <iostream>
#include <cstdio>
//#include <strng>
#include <cstring>
using namespace std;

int n,m,k;
int f[10100];
void init()
{
  memset(f,0,sizeof(f));
}

void solve()
{

  for(int i=2;i<=n;i++)
   f[i]=(f[i-1]+k) % i;
   int answer;
   answer=(m-k+1+f[n]) % n;
   if(answer<=0)
   answer=(answer+n)%n;   //不能这么写,如果answer==0,答案就为0了
   printf("%d\n",answer);

}

int main()
{

  // freopen("test.txt","r",stdin);
    while(~scanf("%d%d%d",&n,&k,&m))
    {
      if(n==0 && m==0 && k==0)
      break;
      init();
      solve();
    }

    return 0;
}
时间: 2024-08-01 03:49:20

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 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 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)时间内完成  类似上一道插队的题  线段树维护对应区间还有多少个人没出队  那么当我们知道出队的人在剩余人中排第几个

NYOJ 191 &amp;&amp; POJ 1012 Joseph(约瑟夫环问题)

链接:click here~~ 题意:假设有2k个人围着一个圆桌坐着,前k个是好人,后k个是坏人 .现在开始,每m个人踢掉一个,比如有6个人,m=5,那么,被踢掉的人依次是5,4,6,2,3,1.现在要求,在踢掉第一个好人前,必需把所有的坏人踢掉,问,给定一个k,求满足这个要求的最小的m,现在希望你写一个程序,快速的帮助小珂,计算出来这个m. 思路:我们来回想一下最基本的约瑟夫环问题, n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数.求最后余下的人编号

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, -