题目
一间屋子里有100盏灯排成一行,按从左至右的顺序编号1、2、3、4、5…99、100,每盏灯都有一个开关,开始全部都关着,现有100个学生,
- 1、第1个学生按了1的倍数的灯,也就说被按灯的编号为:1、2、3、4、5、6、7、8…99、100
- 2、第2个学生按了2的倍数的灯,也就说被按灯的编号为:2、4、6、8、10…98、100
- 3、第3个学生按了3的倍数的灯,也就说被按灯的编号为:3、6、9、12…99
- 4、以此类推…
- 100、第100个学生把100的倍数灯,,也就说被按灯的编号为:100
把结束之后还亮着的灯列出来。
解法一
Go:
ans := make(map[int]bool, 101)
for i := 1; i <= 100; i++ {
for j := i; j <= 100; j = j + i {
ans[j] = !ans[j]
}
}
var res []int
for i := 1; i <= 101; i++ {
if ans[i] {
res = append(res, i)
}
}
return res
PHP:
$ans = [];
for ($i = 1; $i <= 100; $i++) {
$j = $i;
while ($j <= 100) {
if (isset($ans[$j])) {
if ($ans[$j] == 1 ) {
unset($ans[$j]);
} else {
$ans[$j] = 1;
}
} else {
$ans[$j] = 1;
}
$j += $i;
}
}
$ans = array_keys($ans);
return $ans;
解法二
思路:
其实就是求1-100中,完全平方数有几个?为什么是求1-100中的完全平方数,下面详解。
因为灯开始都是关着的,所以某一个灯被按了奇数次,灯就是开的。现在我们只要得到被按奇数次的灯的编号即可得到结果。
我们通过画图模拟这一场景,只模拟10盏灯的情况。
总结一下:
1号灯:被按了1次,仅被第1个学生按了
2号灯:被按了2次,被第1和第2个学生按了
3号灯:被按了2次,被第1和第3个学生按了
4号灯:被按了3次,被第1、第2和第4个学生按了
5号灯:被按了2次,被第1和第5个学生按了
6号灯:被按了4次,被第1、第2、第3和第6个学生按了
7号灯:被按了2次,被第1和第7个学生按了
8号灯:被按了4次,被第1、第2、第4、和第8个学生按了
9号灯:被按了3次,被第1、第3和第9个学生按了
10号灯:被按了2次,被第1和第10个学生按了
上面我们得出,灯只要被按了奇数次,灯就是开的,所以1、4、9号灯是开的,这跟画图模拟结果一致。
下面分析一下:
1号灯是开的,1号学生按了
4号灯是开的,分别由1、2、4号学生按了;
依次来推…
8号灯是关的,分别由1、2、4、8号学生按了;
9号灯是开的,分别由1、3、9号学生按了;
基于上面的结果我们猜测:每盏灯按的次数与灯的编号所含约数的个数有关。 比如4号灯,4的约数为 1、2、4,所以4号灯被按了3次。比如8号灯,8的约数是 1、2、4、8,所以8号灯被按了4次。9号灯同理。所以我们只要找到1~100这些数中约数个数是奇数的数。
什么是约数,不知道的百度。那1~100中哪些数的约数的个数是奇数?一般来说,一个数的约数都是成对出现的,所以一般一个数的约数的个数都是偶数,如上述8的约数 1、2、4、8。
但是也有例外:
如9的约数有 1、3、9
如16的约数有 1、2、4、8、16
如36的约数有 1、2、3、4、6、9、12、18、36
上面举例9、16、36的约数的个数都是奇数,为什么?因为有一个约数相等了,如 9 的约数有 1、3、3、9,但是3是相等的,所以去掉一个。同理16、36约数的个数是奇数的原因都是如此。
所以我们得出结论,约数个数为奇数的数就是一个完全平方数。
这个结论与解法一相同。综上我们得出,100盏灯的问题其实就是求1-100中,完全平方数有几个。