hdu1443 Joseph

来源:互联网 发布:javascript按钮弹窗 编辑:程序博客网 时间:2024/06/05 22:49
Problem Description
The Joseph\\\\\\\'s problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved.

Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.
 
Input
The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.
 
Output
            The output file will consist of separate lines containing m corresponding to k in the input file.
 
Sample Input
340
 
Sample Output
530
 
自己没做出来,看了网上的资料才弄出来,对大牛们表示由衷的敬佩,先看看代码吧!
#include<iostream>using namespace std;bool Jos(int k,int m){    int start = 0;   ///start用来标记第一个好人的编号    int last = k-1;    ///last用来标记最后一个好人的编号    int out;      ///出局的人的编号    for(int i=2*k; i>k; i--)    {        out = (m-1)%i;        if(out>=start&&out<=last)///出局的人在start和last之间则说明把好人杀了        {                        ///此时说明不成立            return false;        }        else  ///出局一个坏人之后需要更新start和last,为什么?一会儿讲。        {            start = ((start - m)%i+i)%i;            last = ((last - m)%i+i)%i;        }    }    return true;}int main(){    int ans[15];    for(int i=1;i<14;i++)    {        for(int j=1; ;j++)        {            if(Jos(i,j))            {                ans[i] = j;                break;            }        }    }    int k;    while(cin>>k)    {        if(0==k)        {            break;        }        else        {            cout<<ans[k]<<endl;        }    }    return 0;}
这里其余的地方都比较好理解,唯一需要费电脑筋的可能就是start和last的更新问题,为什么更新?这当中的过程又是什么?我们那题目中给的n=6,m=5来说明
n=6的时候前三个人是好人,后三个人是坏人,从第一个好人开始报数(报数的时候都是从1开始,不过我们这里1的编号是0),注意:红色部分是好人
最开始:
数组编号:0  1  2  3  4  5
实际编号:1  2  3  4  5  6
第一次报数的时候,5被踢了出去,只剩下1 2 3 4 6还在,第二次报数的时候显然得是编号为5开始报数字1,所以第二次报数的时候应该是这样:
数组编号:0  1  2  3  4
实际编号:6  1  2  3  4  
……
依次类推,直到只剩下1 2 3为止。同时,通过红色的数字,我们发现,每一次报数的时候,好人的范围都变了(第一次报数好人编号是0  1  2,而第二次是1  2  3)。那么每次变化都遵循什么规律,通过总结是这个规律:start = ((start-m)%i+i)%i,last = ((last-m)%i+i)%i,其中i代表本次报数的总人数。(这里像大牛们表示敬意,换成是我的话,我可能都总结不出这个公式)。
0 0