约瑟夫环问题其实非常简单,就是一圈人,每次挂掉第k个,下次从他的下一个开始数,再挂掉第k个,直到剩下一个为止。其中k可以是固定的,也可以是变化的。
约瑟夫问题模拟的复杂度较高,采用递推是比较合理的方式。
假设有n个人,每次杀死k个。
第一次杀死前编号如下:
0 1 2 … k-1 k k+1 … n-2 n-1 (1)
第一次杀死后编号如下:
0 1 2 … k-2 k k+1 … n-2 n-1 (2)
那么下一次开始的时候就要这么看这个编号:
k k+1 k+2 … n-2 n-1 0 1 2 … k-2 (3)
将此编号重新排列:
0 1 2 … n-2-k n-1-k n-k … n-2 (4)
对比(3) (4)可以推导出公式:
x’=(x+k) mod n
其中x’是上一轮的编号,x是后一轮的编号,k为上一轮杀死的人,n为上一轮的人数。
例如:http://acm.hdu.edu.cn/showproblem.php?pid=5643在这里有汉语翻译http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=677&pid=1004
代码如下:
/***************************************************************
File Name: 1004.cpp
Author: wxc575843
Mail: wxc575843@163.com
Created Time: 六 3/12 21:59:54 2016
**************************************************************/
#include<iostream>
using namespace std;
int dp[5000];
void solve(){
dp[0]=0;
int n;
cin>>n;
for(int i=1;i<n;i++){
dp[i]=(dp[i-1]+n-i)%(i+1);
}
dp[n-1]++;
cout<<dp[n-1]<<endl;
}
int main(){
int n;
cin>>n;
while(n--){
solve();
}
}