本题为经典约瑟夫问题。
有约瑟夫经典公式:ans[i]=(ans[i-1]+m)%i表示i个人报数,最终胜利者的编号。
本题与原本约瑟夫问题的不同点在于共有2k个人,要杀掉后k人保留前k人。而原约瑟夫问题为杀掉除自己外的所有人。所以在写代码时应注意。
1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4 int main(){
5 int k=0,n=0,ans[15],count[20],m;//ans[i]表示留下k个人时且杀死所有坏人的最小编号m。
6 //count[i]表示i个人报数每报到m时杀死人的编号。
7 count[0]=0;
8 memset(ans,0,sizeof(ans));
9 while(cin>>k){
10 if(k==0)
11 break;
12 m=1;
13 n=2*k;
14 for(int i=1;i<=k;i++){
15 count[i]=(count[i-1]+(m-1))%(n-i+1);//后面的除数为求编号时,考虑到m可能大于存活者人数,所有人轮过一次后新一轮才进行杀人的情况。
16 if(count[i]<k){//杀到好人了,则此m不符合要求,m递增,i重头再来。
17 m++;
18 i=0;
19 }
20 }
21 ans[k]=m;
22 cout<<ans[k]<<endl;
23 }
24 return 0;
25 }