一开始用的不是约瑟夫置换:
关键是要储存之前求出的值。
因为只有13个数,所以也可以另开程序手动求出所有k值塞进数组,这样每次查找都是o(1),0ms了
首先m值必须在[k+1+2kn,2k(n+1)],n=0,1,2……之间,然后
枚举。
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
#include<fstream>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)
#define sqr(i) ((i)*(i))
#define pii pair<int,int>
#define mp make_pair
#define FOR(i,b,e) for(int i=b;i<=e;i++)
#define FORE(i,b,e) for(int i=b;i>=e;i--)
#define ms(a) memset(a,0,sizeof(a))
const int maxnum =21252;
const int mod = 10007;
int n;
int ssum,st;
//
//#define _DEBUG_ 1
int k[14];
int oh(){
int i=0;
int l=n+1,r=n+n;int last=0,pos;
while(1){
l=n+1+i*2*n,r=n+n+i*2*n;
FOR(m,l,r){
last=0;
FOR(j,0,n-1){
pos = (m-last-1)%(2*n-j);
if(pos<n)break;
last = 2*n-1-j-pos;
if(j==n-1)return m;
}
}
i++;
}
}
int main()
{
#ifdef _DEBUG_
fstream fin("G:/1.txt");
#else
#define fin cin
#endif
ms(k);
for(;;){
fin>>n;
if(!n)
break;
if(!k[n])
k[n]=oh();
printf("%d\n",k[n]);
}
return 0;
}
约瑟夫置换:
先百度约瑟夫环
1、当前轮共有n人,那么将杀掉(m-1)%n+1人
2、假设这一轮杀掉的人为Ans[i],那么下一轮从Ans[i]+1 开始=1
3、下一轮数字转换成这一轮的公式推出:X=(X'+ANS[i]-2)%(n-1)+1注意这里之所以对n-1求余,是因为这里的人数是本轮被杀掉以后剩下的人数,为1~n-1
4、由1得下一轮将杀掉第(m-1)%(n-1)+1;
5、那么下一轮杀掉的人在本轮的位置是ans[i+1]=((m-1)%(n-1)+1+ANS[i]-1)%(n-1)+1=(ans[i]+m-2)%(n-1)+1,如果落到[1,k]里则m不适合
6、假设第0轮有n+1个人,杀掉第0个。
7、优化,m应从k+1开始
http://blog.csdn.net/lyy289065406/article/details/6648444