UVA130 HDU1628 Roman Roulette【vector】【约瑟夫问题】

来源:互联网 发布:支付宝绑定淘宝账户 编辑:程序博客网 时间:2024/06/07 06:43
Roman Roulette


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 167    Accepted Submission(s): 63

Problem Description
The historian Flavius Josephus relates how, in the Romano-Jewish conflict of 67 A.D., the Romans took the town of Jotapata which he was commanding. Escaping, Jospehus found himself trapped in a cave with 40 companions. The Romans discovered his whereabouts and invited him to surrender, but his companions refused to allow him to do so. He therefore suggested that they kill each other, one by one, the order to be decided by lot. Tradition has it that the means for effecting the lot was to stand in a circle, and, beginning at some point, count round, every third person being killed in turn. The sole survivor of this process was Josephus, who then surrendered to the Romans. Which begs the question: had Josephus previously practised quietly with 41 stones in a dark corner, or had he calculated mathematically that he should adopt the 31st position in order to survive? 

Having read an account of this gruesome event you become obsessed with the fear that you will find yourself in a similar situation at some time in the future. In order to prepare yourself for such an eventuality you decide to write a program to run on your hand-held PC which will determine the position that the counting process should start in order to ensure that you will be the sole survivor. 

In particular, your program should be able to handle the following variation of the processes described by Josephus. n > 0 people are initially arranged in a circle, facing inwards, and numbered from 1 to n. The numbering from 1 to n proceeds consecutively in a clockwise direction. Your allocated number is 1. Starting with person number i, counting starts in a clockwise direction, until we get to person number k (k > 0), who is promptly killed. We then proceed to count a further k people in a clockwise direction, starting with the person immediately to the left of the victim. The person number k so selected has the job of burying the victim, and then returning to the position in the circle that the victim had previously occupied. Counting then proceeeds from the person to his immediate left, with the kth person being killed, and so on, until only one person remains. 

For example, when n = 5, and k = 2, and i = 1, the order of execution is 2, 5, 3, and 1. The survivor is 4.

Input
Your program must read input lines containing values for n and k (in that order), and for each input line output the number of the person with which the counting should begin in order to ensure that you are the sole survivor. For example, in the above case the safe starting position is 3. Input will be terminated by a line containing values of 0 for n and k. 

Your program may assume a maximum of 100 people taking part in this event.
 
Sample Input
1 1
1 5
0 0
 
Sample Output
1
1
 
Source

uva


题目大意:题目非常难理解。N个人排成一个圈,按顺时针从1到N编号。从1开始顺时针

数k个人,第k个人出圈(被杀者),从出圈的下一个人开始再数k个人,第k个人(埋葬着)移

到刚才出圈人(被杀者)的位置上。然后从刚才出圈人(即现在埋葬者站的位置上),从出圈者

下一个人继续开始数k个人……,重复这个过程,直到只剩下一个人。例如当N=5,k=2时。

刚开始为:1 2 3 4 5

第一次从1开始数,2出圈,4到2的位置上。变为 1 4 3 5。

第二次从3开始数,5出圈,4到5的位置上。变为 1 3 4。

第三次从1开始数,3出圈,1到3的位置上。变为 1 4。

第四次从4开始数,1出圈,4到1的位置上。变为 4。

刚开始从1开始进行这个游戏,经过四次循环,剩下4是幸存者。

假若现从2开始进行这个游戏,最终5是幸存者。

假若先从3开始进行这个游戏,最终1是幸存者。

。。。。。

现在为了使得1最终成为幸存者,问:从编号多少开始,才能使得1变成幸存者?

思路:先求得从1开始,最终留下幸存者的编号是多少。根据规律,从1号开始计

数,最后能幸存的人编号p,那么从你前面第p个人开始计数,最后能幸存的就是

我自己,这时候我就是1号。序列变成p,p+1,p+2,…,n,1,2,3,…,p-1

1所在的新编号为(n-p+2),但是结果可能超过n,所以采用编号0~n-1,结果为

(n-p+1)%n+1。

参考博文:http://www.cnblogs.com/devymex/archive/2010/09/04/1813034.html


#include<stdio.h>#include<string.h>#include<vector>#include<iostream>#include<algorithm>using namespace std;vector<int> v;int main(){    int n,k;    while(~scanf("%d%d",&n,&k) &&(n||k))    {        v.clear();        for(int i = 1; i <= n; i++)             v.push_back(i);        int m = (k-1)%v.size(),t;        while(v.size() > 1)        {            t = (m + (k-1)) % (v.size()-1);            if(t >= m)                t = (t+1) % v.size();            else                t = t % v.size();            v[m] = v[t];            v.erase(v.begin()+t);            if(t >= m)                m = (m + k)%v.size();            else                m = (m + k-1)%v.size();        }        printf("%d\n",(n-(v.front()-1))%n+1);    }    return 0;}





0 0