/* 功能Function Description: 约瑟夫环+枚举 POJ-1012
开发环境Environment: DEV C++ 4.9.9.1
技术特点Technique:
版本Version:
作者Author: 可笑痴狂
日期Date: 20120731
备注Notes:
大致题意:
有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k)
现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去。
问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉?
PS:当前一轮第m个人死去后,下一轮的编号为1的人 为 前一轮编号为m+1的人
前一轮恰好是最后一个人死掉,则下一轮循环回到开头那个人报“1”
*/
/*
//代码一:用顺序表实现---枚举( 超时TLE)
#include<stdio.h>
#include<malloc.h>
int main()
{
int *base;
int i,k,j,t,flag,sum;
while(scanf("%d",&k),k)
{
base=(int *)malloc((2*k)*sizeof(int));
flag=1;
for(i=k+1;flag;++i) //从k+1开始向后枚举
{
sum=k*2; //sum 存储总人数
for(t=0;t<2*k;++t) //每次都要重新初始化
base[t]=t+1;
for(j=(i-1)%sum;;) //j存储每次去除的人的下标
{
if(base[j]<=k)
break;
for(t=j+1;t<sum;++t) //删除该节点---后边元素依此前移
base[t-1]=base[t];
--sum;
if(sum==k)
{
flag=0;
printf("%d\n",i);
break;
}
j=(j+i-1)%sum;
}
}
free(base);
}
return 0;
}
*/
/*
//代码二:把代码一中打表(AC)
#include<stdio.h>
int main()
{
int k;
int Joseph[14]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
while(scanf("%d",&k),k)
printf("%d\n",Joseph[k]);
return 0;
}
*/
//代码三:用数学方法递推
//出处:http://blog.csdn.net/lyy289065406/article/details/6648444
/*
递推公式为:
ans[i]; //第i轮杀掉 对应当前轮的编号为ans[i]的人
ans[0]=0;
ans[i]=(ans[i-1]+m-1)%(n-i+1); (i>1 , 总人数n=2k 则n-i为第i轮剩余的人数)
*/
//Memory Time
//184K 250MS
#include<iostream>
using namespace std;
int main(void)
{
int Joseph[14]={0}; //打表,保存各个k值对应的m值
int k;
while(cin>>k)
{
if(!k)
break;
if(Joseph[k])
{
cout<<Joseph[k]<<endl;
continue;
}
int n=2*k; //总人数
int ans[30]={0}; //第i轮杀掉 对应当前轮的编号为ans[i]的人
//PS:每一轮都以报数为“1”的人开始重新编号
int m=1; //所求的最少的报数
for(int i=1;i<=k;i++) //轮数
{
ans[i]=(ans[i-1]+m-1)%(n-i+1); //n-i为剩余的人数
if(ans[i]<k) //把好人杀掉了,m值不是所求
{
i=0;
m++; //枚举m值
}
}
Joseph[k]=m;
cout<<m<<endl;
}
return 0;
}