Description
有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k)
现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去。问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉?
Input
多组输入,每组一个整数k(k<14),以0结束输入
Output
对于每组k,输出符合条件的m
Sample Input
3
4
0
Sample Output
5
30
Solution
经典约瑟夫问题
k值很小,暴力枚举m
递推公式为:
ans[i]; //第i轮杀掉对应当前轮的编号为ans[i]的人
ans[0]=0;
ans[i]=(ans[i-1]+m-1)%(n-i+1); (i>1,2*k-i为第i轮剩余的人数)
注意:
1.本题从1开始报数
2.记录每次k值对应的m值,下次遇到同样k值直接输出即可
Code
#include<stdio.h>
int a[15];
int main()
{
int k;
while(scanf("%d",&k)&&k!=0)
{
int i,j,m=k,s;//m从k开始枚举,保证第一个杀的是坏人
if(a[k])//如果之前已经询问过k,直接输出对应m值
{
printf("%d\n",a[k]);
continue;
}
int ans[30]={0};//第i轮杀掉对应当前轮的编号为ans[i]的人
for(int i=1;i<=k;i++)//轮数
{
ans[i]=(ans[i-1]+m-1)%(2*k-i+1);//2*k-i为剩余的人数
if(ans[i]<k)//把好人杀掉了,m值不是所求
{
i=0;//每一轮都以报数为1的人开始重新编号
m++;//枚举m值
}
}
printf("%d\n",m);
a[k]=m;//记录每个k值的可行解,避免重复计算
}
return 0;
}