题目描述
约瑟夫问题来源于公元1世纪的犹太历史学家Josephus。问题描述,有n个人(分别以编号1,2,3...n表示)围成一个圆圈,从编号为1的人开始进行1~m正向报数,报到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;如此重复下去,直到所有的人全部出列,求最后一个出列人的编号
输入
输入文件仅有一行包含二个用空格隔开的整数N,M (2≤N≤100000,M≤1000000000)。
输出
输出文件仅有一行包含一个整数表示一个整数,表示最后一个人在队列中的编号。
样例
输入
8 3
输出
7
代码1
#include <iostream>
using namespace std;
int josephus(int n, int m) {
if (n == 1) {
return 1; // 只剩一个人时,编号为1的人是最后一个出列的
} else {
// 递归求解约瑟夫问题
return (josephus(n - 1, m) + m - 1) % n + 1;
}
}
int main() {
int N, M;
cout << "请输入N和M:" << endl;
cin >> N >> M;
int result = josephus(N, M);
cout << result << endl;
return 0;
}
代码2
#include <iostream>
#include <list>
using namespace std;
int josephus(int n, int m) {
list<int> people; // 使用链表来表示所有人的队列
for (int i = 1; i <= n; i++) {
people.push_back(i); // 初始化队列,按照编号依次插入链表尾部
}
auto curr = people.begin(); // 当前报数人的迭代器
while (people.size() > 1) {
for (int i = 1; i < m; i++) {
curr++;
if (curr == people.end()) {
curr = people.begin(); // 如果到达链表末尾,重新指向链表头部
}
}
curr = people.erase(curr); // 报到m的人出列,返回下一个报数人的迭代器
if (curr == people.end()) {
curr = people.begin(); // 如果到达链表末尾,重新指向链表头部
}
}
return *people.begin(); // 返回最后一个出列人的编号
}
int main() {
int N, M;
cout << "请输入N和M:" << endl;
cin >> N >> M;
int result = josephus(N, M);
cout << result << endl;
return 0;
}