Joseph
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 56348 | Accepted: 21526 |
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.
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
分析:
1、先推了下公式:设存在k个好人为0,1,...,k-1;存在k个坏人k,k+1,...,2k;设x属于自然数,则m属于[k+1+2kx, 2k+2kx]。也就是说,m的【第一轮】命中一定在坏人段。(尝试再推第二轮命中,但是没有推出合适的公式)
2、这个题其实做了3次:
第一次用公式+打标签的方式。发现在k>8时,要跑很久很久。
第二次用公式+循环链表的方式。发现在k>10时,要跑很久很久。
第三次,忽然意识到,我只需要输出k,而不需要输出被踢掉的坏人序号,所以不需要维护坏人序号。那么比如0,1,2,3,4,5的人,第一次被干掉的是4,正常来说,队伍就变成0,1,2,3,5。由于不需要维护坏人的序号,那么就可以认为队伍为0,1,2,3,4。
3、存一下每个k对应的m值,poj的用例有重复。
1 #include <stdio.h> 2 3 typedef int BOOL; 4 5 #define TRUE 0 6 #define FALSE 1 7 8 #define MAX_NUM 14 9 10 BOOL CheckM(int m, int k) 11 { 12 int i = 0, len = 2*k; 13 int badDead = 0; 14 15 while(badDead < k) 16 { 17 i = (i+m-1)%len; 18 if(i < k) return FALSE; 19 len--; 20 i %= len; 21 badDead++; 22 } 23 return TRUE; 24 } 25 26 int CalcM(int k) 27 { 28 int x, m = 0; 29 30 for(x = 0; x < 10000000; x++) 31 { 32 for(m = k+1+2*k*x; m <= 2*k*x+2*k; m++) 33 { 34 if(TRUE == CheckM(m, k)) return m; 35 } 36 } 37 return 0; 38 } 39 40 int main() 41 { 42 int k = 0; 43 int rst = 0; 44 int ans[MAX_NUM] = {0}; 45 46 while(1 == scanf("%d", &k) && k > 0) 47 { 48 if(ans[k] == 0) 49 { 50 rst = CalcM(k); 51 ans[k] = rst; 52 } 53 else 54 { 55 rst = ans[k]; 56 } 57 printf("%d\n", rst); 58 } 59 60 return 0; 61 }