本题为经典约瑟夫问题。
有约瑟夫经典公式: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 }