题目描述
在一条无限长的路上,有一排无限长的路灯,编号为 1 , 2 , 3 , 4 , ... 1,2,3,4,\dots 1,2,3,4,...。
每一盏灯只有两种可能的状态,开或者关。如果按一下某一盏灯的开关,那么这盏灯的状态将发生改变。如果原来是开,将变成关。如果原来是关,将变成开。
在刚开始的时候,所有的灯都是关的。小明每次可以进行如下的操作:
指定两个数, a , t a,t a,t( a a a 为实数, t t t 为正整数)。将编号为 ⌊ a ⌋ , ⌊ 2 × a ⌋ , ⌊ 3 × a ⌋ , ... , ⌊ t × a ⌋ \lfloor a\rfloor,\lfloor 2 \times a\rfloor,\lfloor3 \times a\rfloor,\dots,\lfloor t \times a\rfloor ⌊a⌋,⌊2×a⌋,⌊3×a⌋,...,⌊t×a⌋ 的灯的开关各按一次。其中 ⌊ k ⌋ \lfloor k \rfloor ⌊k⌋ 表示实数 k k k 的整数部分。
在小明进行了 n n n 次操作后,小明突然发现,这个时候只有一盏灯是开的,小明很想知道这盏灯的编号,可是这盏灯离小明太远了,小明看不清编号是多少。
幸好,小明还记得之前的 n n n 次操作。于是小明找到了你,你能帮他计算出这盏开着的灯的编号吗?
输入格式
第一行一个正整数 n n n,表示 n n n 次操作。
接下来有 n n n 行,每行两个数, a i , t i a_i,t_i ai,ti。其中 a i a_i ai 是实数,小数点后一定有 6 6 6 位, t i t_i ti 是正整数。
输出格式
仅一个正整数,那盏开着的灯的编号。
1.题目分析
分析一下大概的题意:对自然数编号的无限盏灯(初始灯全是关的)进行N次操作,每一次操作给出两个数,确定此次操作灯的编号,而每一次具体的操作就是将指定编号的灯开变关,关变开,求最后还亮着灯的编号。
2.题目思路
定义一个足够长的数组表示灯的开关情况,1表示亮,0表示灭。
循环N次操作,每一次操作输入A,T,A向下取整确定开始的位置,A*T向下取整确定结束的位置,
再嵌套一个for循环,执行开关灯操作,值得一提的是,这里索引不是加加,而是计数器从1到某个位置与A的积,跳出循环的条件则是积大于结束位置的时候,注意!!! 每一次操作完成之后,需要把计数器重置。
最后循环遍历数组,统计最后一盏灯的编号,即为1的元素。
3.代码实现
c
#include <stdio.h>
#include <math.h>
int main() {
//表示灯的情况 0 表示关,1表示开
int arr[2000000] = {0};
int n;
double a, t;
scanf("%d", &n);
int start = 0;
int end = 0;
int cnt = 1;
for (int i = 0; i < n; ++i) {
scanf("%lf %lf", &a, &t);
//每一轮开关的开始
start = floor(a);
//开关的结束
end = floor(a * t);
for (int j = start; j <= end; j = floor(1.0 * cnt * a)) {
//开灯操作
if (arr[j] == 0) {
arr[j] = 1;
} else {
//关灯操作
arr[j] = 0;
}
cnt++;
}
//重置为1,很重要!!!
cnt = 1;
}
//统计最后一盏灯的编号
for (int i = 0; i < 2000000; ++i) {
if (arr[i] == 1) {
printf("%d ", i);
break;
}
}
return 0;
}