问题分析与解题思路
根据搜索结果和题目描述,这是一个经典的开关灯问题,可以通过两种方法解决:
方法一:模拟法
直接模拟每个人对灯的操作,记录每盏灯的最终状态。这种方法直观易懂,适合N和M较小的情况(题目中N≤5000,完全适用)。
方法二:数学公式法
通过分析灯的开关次数,发现只有当灯的编号的因数个数为奇数时,灯最终才会关闭。而一个数的因数个数为奇数当且仅当该数是完全平方数。但需要注意题目中的初始状态和操作顺序与标准问题略有不同,需要调整。
符合要求的C++代码(模拟法)
代码说明
变量名说明(均≤3字符)
变量名 含义解释
N 灯的总数
M 人的总数
i,j 循环变量
cnt 关闭的灯的数量
light 存储灯的状态的数组
result 存储关闭的灯的编号的数组
关键逻辑:
初始状态:所有灯都处于开启状态
第一个人操作:将所有灯关闭
后续人操作:第i个人切换所有编号为i的倍数的灯的状态
结果收集:收集所有关闭的灯的编号并输出
优化版本(数学公式法)
测试用例验证
输入#1:
6 3
输出:
1,5,6
验证:
灯1:被第1个人关闭,之后没有被操作,最终关闭
灯2:被第1个人关闭,被第2个人打开,最终打开
灯3:被第1个人关闭,被第3个人打开,最终打开
灯4:被第1个人关闭,被第2个人打开,最终打开
灯5:被第1个人关闭,之后没有被操作,最终关闭
灯6:被第1个人关闭,被第2个人打开,被第3个人关闭,最终关闭
性能对比
方法 时间复杂度 空间复杂度 优点 缺点
模拟法 O(NM) O(N) 直观易懂,容易实现 当M接近N时,时间复杂度较高
公式法 O(Nsqrt(N)) O(N) 效率更高,尤其是当M接近N时 需要理解数学原理