假设有 N 盏灯(N 为不大于 5000 的正整数),从 1 到 N 按顺序依次编号,初始时全部处于开启状态;有 M 个人(M 为不大于 N 的正整数)也从 1 到 M 依次编号。第一个人(1 号)将灯全部关闭,第二个人(2 号)将编号为 2 的倍数的灯打开,第三个人(3 号)将编号为 3 的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和 3 号一样,将凡是自己编号倍数的灯做相反处理。请问:当第 M 个人操作之后,哪几盏灯是关闭的,按从小到大输出其编号,其间用逗号间隔。
时间: 2024-03-23 14:41:31 浏览: 105
关灯
这个问题可以使用数组进行模拟,代码如下:
```c++
#include <iostream>
#include <cstring>
using namespace std;
const int N = 5010;
bool lights[N];
int main() {
int n, m;
cin >> n >> m;
memset(lights, true, sizeof(lights)); // 初始化所有灯都是打开状态
for (int i = 1; i <= m; i++) {
for (int j = i; j <= n; j += i) { // 操作编号为 i 的人会改变所有编号是 i 的倍数的灯
lights[j] = !lights[j]; // 翻转灯的状态
}
}
bool first = true; // 控制输出格式
for (int i = 1; i <= n; i++) {
if (!lights[i]) {
if (first) first = false;
else cout << ",";
cout << i;
}
}
cout << endl;
return 0;
}
```
该程序首先读入灯的总数 `n` 和操作的人数 `m`,然后使用 `memset` 函数将所有灯的状态都初始化为打开状态。接下来,使用双重循环来模拟每个人对灯的操作,外层循环控制操作的人数,内层循环控制操作的灯的编号。内层循环中的步长为操作人的编号,这样就可以保证只有符合该操作人的倍数的灯才会受到影响。
操作完所有的人之后,再次遍历所有的灯,将关闭状态的灯的编号输出即可。
阅读全文