约瑟夫问题
前k个好人和后k个坏人排在一起
要求先删除全部坏人才能删除好人
暴力vector模拟一下。。打表交。。
int ans[15]={-1,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881}; 以下是暴力模拟。。。答案当然是打表啦。。
//只有 (k+1)的倍数加1或者0 才可能是答案
这个结论是推出来的。。很容易推 当删除最后一个坏人时必定有两种情况
1 、 倒数第二个人是在他前面,那么接下来他是 序号1 ,有 m%(k+1)>k 即 m%(k+1)==k+1
所以 m会是k+1的倍数
2、倒数第二个人在他后面,接下来他是序号k+1,从1开始数起,
要满足 (m-1) % (1+k) >k 即 (m-1) % (1+k) ==k+1
所以 m会是k+1的倍数+1
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <list>
#include <vector>
using namespace std;
int n;
int i,j;
int k,h;
int max(int a,int b)
{return a<b?b:a;}
vector <int >sb;
vector <int >::iterator it;
int main()
{
while(cin>>k&&k)
{
int line=0;
int m;
for (i=1;i<=20000000;i++) //随便设置的次数
{
line=!line;
if (!line)
m=i*(k+1)+1; //只有 (k+1)的倍数加1或者0 才可能是答案
else
m=i*(k+1);
if (line) i--;
sb.clear();
for (j=1;j<=k;j++)
sb.push_back(1);
for (j=1;j<=k;j++)
sb.push_back(2);
int kill=0;
int p=0;
while(1)
{
p=(p+m-1)%sb.size(); //暴力模拟
if (sb[p]==2)
{
it=&sb[p];
sb.erase(it);
kill++;
}
else
break;
if (kill==k)break;
}
if (kill==k)
{
printf("%d\n",m);
break;
}
}
}
return 0;
}