poj 1012 约瑟夫置换

一开始用的不是约瑟夫置换:

关键是要储存之前求出的值。

因为只有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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值