Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 29666 Accepted: 11043

    本题如果采用传统的模拟的方法很容易超时,因此必须采用数学方法,当然本题数据比较小,如果先用暴力求出数据然后再打表也能成功,但是显示不出水平。下面介绍一种递推+打表的方法:

   代码:

 

1 #include <stdio.h>
2  int test(int k,int m)
3 {
4 int i,j=0,n=k*2;
5 for(i=0;i<k;i++)
6 {
7 j=(j+m-1)%(n-i);//约瑟夫环公式
8 if(j<k) return 0;//根据题意肯定没有出现在K以内的
9 }
10 return 1;
11 }
12 int main()
13 {
14 int i,j,k;
15 int x[14];
16 for(k=1;k<14;k++)
17 {
18 i=k+1;
19 while(1)
20 {
21 if(test(k,i))
22 {
23 x[k]=i;
24 break;
25 }
26 if(test(k,i+1))
27 {
28 x[k]=i+1;
29 break;
30 }
31 i+=(k+1);
32 }
33 }
34 while(scanf("%d",&k),k)
35 {
36 printf("%d\n",x[k]);
37 }
38 }
39

 

  注意:

本题有几点需要注意,否则很容易超时,第一、运用公式j=(j+m-1)%(n-i);推导出下一个出现的元素在第几号位置,如果j<k的话,不符合题意。

第二点。就是m,当只剩下k+1个数的时候,则上一个消失的数一定是在目前仅剩的bad左边或者是右边,所以m%(k+1)==0或者1

有了这两个条件,可以加快程序的速度