有 n 个人围成一圈,顺序排号。从第 1 个人开始报数(从 1 到 3 报数), 凡报到 3 的人退出圈子,问最后留下的是原来第几号的人。c 语言
时间: 2023-12-23 16:08:53 浏览: 30
好的,这是一个经典的约瑟夫问题,可以使用递推公式来解决。以下是 C 语言的解法:
```c
#include <stdio.h>
int josephus(int n, int m) {
int f = 0;
for (int i = 2; i <= n; i++) {
f = (f + m) % i;
}
return f + 1;
}
int main() {
int n, m;
printf("请输入人数 n 和报数 m:");
scanf("%d %d", &n, &m);
int result = josephus(n, m);
printf("最后留下的人是原来第 %d 号的人", result);
return 0;
}
```
代码解释:
1. `josephus` 函数用于解决约瑟夫问题,输入人数 `n` 和报数 `m`,返回最后留下的人的编号。
2. 在循环中,`f` 表示上一轮被删除人的下一个人的编号,每轮根据递推公式 `(f + m) % i` 计算出下一轮被删除人的下一个人的编号。
3. `main` 函数中先输入人数 `n` 和报数 `m`,然后调用 `josephus` 函数解决问题并输出结果。
希望能帮到你!
相关问题
有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问
最后留下的是原来第几号的那位?
这是一个经典的约瑟夫问题。根据引用中的解题思路,我们可以写一个函数来解决这个问题。具体步骤如下:
1. 定义一个大小为n的一维数组,初始化为从1到n。
2. 设一个计数器,按照题述条件,遍历每一个数组元素,并从1到3报数,若当前元素计数为3则将其从数组中删除(即标记该人出局),同时使计数器置0并记录出局人数。
3. 如果出局人数为n-1人(即只剩下1人)终止循环,否则由外层循环控制使得再次遍历数组,直到踢出n-1人。
4. 最后满足只剩1人的条件后,再次遍历数组,找出那个最终没有被踢出的人,并返回其序号。
因此,最后留下的是原来第几号的那位取决于n和报数的规则。如果n=5,报数规则为从1到3,则最后留下的是原来第3号的那位。如果n=10,报数规则为从1到2,则最后留下的是原来第5号的那位。
有n个人围成一圈顺序排号从第一个人开始,报数从1到3报数,凡报到三的人退出圈子,问最后留下的人原来排在第几号?用指针
是一个经典的约瑟夫问题,可以使用循环链表来解决。具体实现如下:
```c++
#include <iostream>
using namespace std;
struct Node {
int num;
Node* next;
Node(int n) : num(n), next(nullptr) {}
};
int main() {
int n;
cout << "请输入总人数:";
cin >> n;
// 构建循环链表
Node* head = new Node(1);
Node* cur = head;
for (int i = 2; i <= n; i++) {
cur->next = new Node(i);
cur = cur->next;
}
cur->next = head;
// 开始报数
int count = 0;
Node* pre = cur;
cur = head;
while (cur->next != cur) {
count++;
if (count == 3) {
count = 0;
pre->next = cur->next;
delete cur;
cur = pre->next;
} else {
pre = cur;
cur = cur->next;
}
}
// 输出最后留下的人的编号
cout << "最后留下的人的编号是:" << cur->num << endl;
// 释放内存
delete cur;
return 0;
}
```