Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 48916 | Accepted: 18476 |
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
3 4 0
Sample Output
5 30
Source
题目大意:约瑟夫问题,有2k个人组成一个环,前k个是好人,后k个是坏人,求最小的m,使得每数m个人淘汰一个人,前k个被淘汰的都是坏人。
思路:模拟题,约瑟夫问题的加强版。因为k不大,我们可以采用试探法。从m=1开始代入计算,直到找到符合条件的m为止。该m即是最小的m。模拟的思路,思考了好久终于理清了。我们把全部人编号,0至k-1为好人,k止2k-1为坏人。每次数到第m个人出局。假设现在第i次杀人结束了,杀掉的人的编号是t,下一次杀人的编号是多少?如果杀掉的是好人,我们很容易确定,编号即为(t+m-1)%(n-i+1)。而如果杀掉的是坏人,则有两种情况,编号比t大或编号比t小,这给我们的编程带来了困难。要求每次杀掉的都是坏人,非常不好求。我们可以换一个思路,只要每次杀掉的不是好人就好。那么,每次被杀掉的人的编号只要小于k就行。而后面的坏人的编号即使混乱了也不要紧,因为只要把大于等于k的人都看成是坏人即可,不需要知道他们的编号。这样,我们就可以一轮轮地模拟下去。
1 /* 2 * Author: Joshua 3 * Created Time: 2015年01月31日 星期六 20时50分27秒 4 * File Name: poj1012.cpp 5 */ 6 #include<cstdio> 7 #include<iostream> 8 #include<cstring> 9 #define maxn 30 10 int k,f[maxn]; 11 12 void cal(int x) 13 { 14 int e[maxn],m=1,n=2*x; 15 bool flag; 16 e[0]=0; 17 while (1) 18 { 19 flag=true; 20 for (int i=1;i<=x;++i) 21 { 22 e[i]=(e[i-1]+m-1)%(n-i+1); 23 if (e[i]<x) 24 { 25 ++m; 26 flag=false; 27 break; 28 } 29 } 30 if (!flag) continue; 31 f[x]=m; 32 break; 33 } 34 } 35 36 int main() 37 { 38 memset(f,0,sizeof(f)); 39 while (scanf("%d",&k)&& k>0) 40 { 41 if (f[k]==0) cal(k); 42 printf("%d\n",f[k]); 43 } 44 return 0; 45 }