题目大意:存在一个约瑟夫环,给出一个k,表示编号是1到k是好人,k+1到2*k是坏人,要求一个最小的m,使得所有的坏人都在好人之前出圈。
解题方法:约瑟夫问题是一个很经典的问题,有下面两个特点:
1)s[i]表示第i个出圈的人是谁,则有s[i]=(s[i]+m-1)%n (这里的n指得是剩下的人数)
2)w[i]表示i个人完报到m则出圈游戏的最后获胜者是谁,则有f[i]=(f[i-1]+m)%i
这题,只要用第一个性质进行模拟就可以了,枚举m的大小,进行验证即可。
1#include <iostream>
2#include <cstdio>
3
4using namespace std;
5
6int a[14];
7bool f(int n,int m)
8{
9 int i,s=1,num=1,k=n;
10 n=n*2;
11 for(i=1;i<=k;i++)
12 {
13 s=(s+m-1)%n;
14 // cout << s << " ";
15 if(s==0)s=n;
16 n--;
17 if(s<=k)return false;
18 } return true;
19}
20int main()
21{
22 int n,i,j,len;
23 for(i=1;i<14;i++)
24 {
25 for(j=i+1;;j++)
26 {
27 if(f(i,j))
28 {a[i]=j; break;}
29 }
30 }
31 while(scanf("%d",&n),n)
32 {printf("%d\n",a[n]);}
33 return 0;
34}
35