luogu-P1161 开灯
GESP C++三级练习,一维数组练习,难度★★☆☆☆。
luogu-P1161 开灯
题目要求
题目描述
在一条无限长的路上,有一排无限长的路灯,编号为 。
每一盏灯只有两种可能的状态,开或者关。如果按一下某一盏灯的开关,那么这盏灯的状态将发生改变。如果原来是开,将变成关。如果原来是关,将变成开。
在刚开始的时候,所有的灯都是关的。小明每次可以进行如下的操作:
指定两个数,( 为实数, 为正整数)。将编号为 的灯的开关各按一次。其中 表示实数 的整数部分。
在小明进行了 次操作后,小明突然发现,这个时候只有一盏灯是开的,小明很想知道这盏灯的编号,可是这盏灯离小明太远了,小明看不清编号是多少。
幸好,小明还记得之前的 次操作。于是小明找到了你,你能帮他计算出这盏开着的灯的编号吗?
输入格式
第一行一个正整数 ,表示 次操作。
接下来有 行,每行两个数,。其中 是实数,小数点后一定有 位, 是正整数。
输出格式
仅一个正整数,那盏开着的灯的编号。
输入输出样例 #1
输入 #1
3
1.618034 13
2.618034 7
1.000000 21
输出 #1
20
说明/提示
记 。
- 对于 的数据,满足 ;
- 对于 的数据,满足 ;
- 对于 的数据,满足 ;
- 对于 的数据,满足 ,,。
数据保证,在经过 次操作后,有且只有一盏灯是开的,不必判错。而且对于所有的 来说, 的最大值不超过 。
题目分析
解题思路
本题的解题思路如下:
问题本质:
- 给定一系列操作,每次操作会按指定规则改变一些灯的状态
- 每个操作包含两个参数:实数 和正整数
- 每次操作会改变编号为 , , …, 的灯的状态
- 最终只有一盏灯是亮着的,需要找出这盏灯的编号
解题关键:
- 核心思路 - 状态模拟:
- 使用数组记录每盏灯的状态:
- 创建一个足够大的数组 (根据题目提示 大小足够)
- 表示灯是关闭的, 表示灯是打开的
- 模拟每次操作:
- 对于每次操作的参数 和
- 计算需要改变状态的灯的编号: ( 从 到 )
- 使用异或操作()切换对应灯的状态
- 最后遍历数组,找到值为 的位置,即为答案
- 使用数组记录每盏灯的状态:
- 核心思路 - 状态模拟:
复杂度分析:
- 时间复杂度:,其中n为操作次数,t_max为单次操作最大次数
- 空间复杂度:,需要一个固定大小的数组存储灯的状态
{% include custom/custom-post-content-inner.html %}
示例代码
#include <iostream>
// 用于存储每个灯的状态的数组,0表示关闭,1表示打开
int array[2000005];
int main() {
// n表示操作次数
int n;
std::cin >> n;
// 循环处理每次操作
for (int i=0; i < n; i++) {
// a为实数倍数,t为操作次数上限
double a;
int t;
std::cin >> a >> t;
// 对于每次操作,计算需要改变状态的灯的编号
for (int j = 1; j <=t; j++) {
// 计算当前需要改变状态的灯的编号
int idx = a * j;
// 使用异或操作切换灯的状态(0变1,1变0)
array[idx] ^= 1;
}
}
// 遍历所有可能的灯,找出唯一一个打开的灯
for (int i=0; i < 2000005; i++) {
// 如果找到值为1的位置,说明这盏灯是打开的
if (array[i] == 1) {
std::cout << i << " ";
}
}
return 0;
}
{% include custom/custom-post-content-footer.md %}
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
“luogu-”系列题目可在 洛谷题库 在线评测。
“bcqm-”系列题目可在 编程启蒙题库 在线评测。
GESP/CSP 认证学习微信公众号

Last updated on