既然题目中提到了约瑟夫环,就先考虑其规律
假设每个人都存储在数组中,a[0],a[1]...a[n-1],共有n个人,每次走m步,则第一轮出局的人坐标为(m-1)%n,第二轮的出局的人为(m-1+第一轮人出局的坐标)%(n-1)。。。。可以得到规律,第i轮出局的人坐标为f(i) = (m-1+f(i-1))%(n-i+1)。
回到原题,k个好人,k个坏人,先出去k个坏人,那么前k轮每轮出局的人的坐标都小于k。但如果从一开始,根据这个条件一个一个的测m值是否满足很明显太慢了。可以考虑所有m满足的共性。
假设剩下最后两个坏人,用g表示好人,b表示坏人,x表示这轮出列的坏人,则序列为:bbbbxg或bbbbgx,而下一轮肯定出去的是最后一个坏人,可以看到m满足条件:m%(k+1) == 0或者m%(k+1) == 1。这样缩小了比较范围。
而此题不打表会超时的,代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int dabiao[14];
bool judge(int m,int k){
int i = 1;
int pos = 0;
int temp;
while( i<= k){
temp = (m-1+pos)%(2*k-i+1);
if(temp<k)
return false;
pos = temp;
++i;
}
return true;
}
int joseph1(int k){
int m = k+1;
int result;
while(true){
if(judge(m,k)){
result = m;
break;
}
if(judge(m+1,k)){
result = m+1;
break;
}
m += (k+1);
}
return result;
}
int main()
{
unsigned short k;
int m;
for(int k =1;k<14;++k){
m = joseph1(k);
dabiao[k] = m;
}
while(cin>>k){
if(k == 0)
break;
cout<<dabiao[k]<<endl;
}
return 0;
}