问题提出:
有编号1~100个灯泡,起初所有的灯都是灭的。有100个同学来按灯泡开关,如果灯是亮的,那么按过开关之后,灯会灭掉。如果灯是灭的,按过开关之后灯会亮。
现在开始按开关。
第 1 个同学,把所有的灯泡开关都按一次(按开关灯的编号:1,2,3,......100)。
第 2 个同学,隔一个灯按一次(按开关灯的编号:2,4,6,......,100)。
第 3 个同学,隔两个灯按一次(按开关灯的编号:3,6,9,......,99)。
......
问题是,在第100个同学按过之后,有多少盏灯是亮着的?
解决思路:
明显这是一个 奇偶问题,一个灯 奇数次是亮着的,偶数次就灭了。
那这个问题就变成了一个判断 奇数偶数 的数学问题。
先最简单的思路,模拟这个过程,light[i][j] 代表 第 i 个人按了第 j 个灯,直接上代码:
/* linolzhang 2008.05
*/
// 搜集过程
int light[100][100];
for(int i=0;i<100;i++)
for(int j=0;j<100;j++)
if(j%i == 0)
{
light[i][j] = 1;
}
// 累加过程(j列对应和为偶数为灭)
int statu[100] = {0};
for(int j=0; j<100; j++)
{
for(int i=0; i<100; i++)
statu[j] += light[i][j];
statu[j] = statu[j] % 2;
}
感觉这个问题已经很完美的解决了?
*也许不是,你应该有更好的思路。
Light 1 只会被第1个同学按;
Light 2 只会被第1个同学和第2个同学按;
Light 3 只会被第1个同学和第3个同学按;
Light 4 只会被第1个同学、第2个同学以及第4个同学按;
……
Light N 只会被第1个同学、……、第N个同学按;
找到规律了吗?没错,这是一个简单的因式分解题,只需要求 该序号N 能被哪些数整除?
int getCount(int num)
{
int count = 0; // 因子个数
for(int i=1;i<num;i++)
if(0==num % i)
count++;
return count;
}; 计算因子个数,因子个数为偶数个,灯是灭的。
*那还有没有第三种解法呢?有
接着上面来看,什么样的编号具有奇数个因子,什么样的编号具有偶数个因子?来看 质因数分解的定理:
任何正数都能被唯一表示成多个质因数幂次乘积的方式。
36 = 2^2 * 3^2(2、3、6)
64 = 2^3 * 2^3 (2、4、8、16、32)
99 = 3^2 * 11 (3、9、33、11)
我们得到结论,只有指数和为偶数次的 其因子才会是奇数个,那么满足这个条件的是哪些呢?
必须满足完全平方数。
ok,我们得到结论,1~100中完全平方数有 1, 4, 9, 16, 25, 36, 49, 64, 81, 100 ,这10个编号的灯是亮着的。
博客探讨了一个有趣的数学问题:100个初始关闭的灯泡由100个学生按特定规则依次开关,最后哪些灯泡会亮着。通过奇偶性分析和因式分解的方法,得出结论,1到100中完全平方数对应的灯泡将会亮起,即10盏灯亮着。
5042

被折叠的 条评论
为什么被折叠?



