约瑟夫环的递归递推问题

关于约瑟夫环的探讨:课堂上学习的约瑟夫环是一个相对较麻烦的方法,而相对精简的是递归的方式。

int josephus(int n, int m) {
	if(n == 1) {
		return 0;
	}
	else {
		return (josephus(n-1, m) + m) % n;
	}
}
 
int main() {
	int n, m;
	while (cin>>n) {
		if (!n) {
			break;
		}
		cin>>m;
		int result = josephus(n, m);
		cout<<result+1<<endl;
	}
	return 0;
}

递归相对比较简单,并没有使用数组结构来一个一个反映出每一局出局的人,而是直接通过递归得到了最终的结果。但是如此递归仍然不够简单。我们知道约瑟夫环问题本质上是一个数学问题,那么可以使用数学的递推思想来解决这样一个问题。这与递归十分相似但更为简单,省去了递归的步骤,虽然方法类似,但由于递归调用函数会使时间增长,所以直接使用数学方法使用for循环时间是更为精简的。
int n;//共n个人
int m;//密码为m
Int a;//胜利者下表为a
//下标为0~n-1,方便取模计算。
假设此时m为3,若11个人时6号活了下来,则当只有十个人的情况时,还可以认为仍然是这个聪明人活了下来,但是他的编号向前移动了三个,因为10个人相当于是11个人中的2号(第三个)出局了,所以此时胜利者下标-3,所以这个聪明人在只有十个人时应该是3号。 反之,每多一个人,这个人想要活下去就要让自己的下标+3,当超过n-1时进行取模回到前面,这样便可以得到递推表达式:a=f(n,m)=[f(n-1,m)+m]%n;
由于只有一个人时胜利者为0号,所以a从0开始,即:

for(int i=2;i<=n;i++)//对一个人没有讨论意义,故从2开始
    a=(a+m)%i;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章