两个有意思的计算机相关的智力题

来源:互联网 发布:淘宝助理5导入csv 编辑:程序博客网 时间:2024/04/30 03:13

1. 亮灯问题:

   现有100盏灯,编号1到100。每盏灯都有一个开关,开始时,100盏灯全部关闭。

   做如下操作:

    <1> . 第1次,按下所有编号是1 的倍数的灯的开关;

   <2> . 第2次,按下所有编号是 2 的倍数的灯的开关;

   <3> . 第3次,按下所有编号是 3 的倍数的灯的开关;

                       ……………………

   <n> . 第n次,按下所有编号是 n 的倍数的灯的开关;

                      …………………………

<100> . 第100次,按下所有编号是 100 的倍数的灯的开关。


问: 经过上述操作后, 总有几盏灯在亮, 他们的编号分别是???



分析: 每盏灯开始都是关着的,最后亮着的那盏的肯定是开关被按下了奇数次。

         而对于每盏灯,都在什么时候灯的开关被按下呢? 

        显然有上述操作可见,该灯的编号是次数的倍数时该灯被的开关被按下。

        反过来,也就是 次数是该灯编号的约数时,该灯的开关被按下。

上述,问题转化,为求灯编号的约数的个数的问题, 

     而亮灯问题转化为灯的编号的约数的个数为奇数的问题。


看到这里,我们学计算机的同学,都禁不住的,要通过编程解决该问题,

我开始也是这样想,也是这样做的。能不能多想一步,灵机一动,不用编程,就能解决呢?

先看一下,怎样通过编程,解决该问题? 更巧妙方法,稍后介绍。(也许编程都的结果,会对你有所启发^o^).(有点像启发式思维,有木有,,,)

#include <stdio.h>#include <stdlib.h>int main(int argc, char *argv[]) {    int i;    int j;    int count; //统计约数的个数;    int n = 0; //统计亮灯的总数;    printf("亮灯的编号是:");    for(i = 1; i <= 100; ++i) {        count = 0;        for(j = 1; j<=i; ++j){            if(i % j == 0) ++count;        }        if(count % 2) {            printf("%d ", i);            ++n;        }    }    printf("\n所有亮着的灯的个数是:%d", n);    return 0;}

运算结果:

result


看到上述结果,如果你只打印亮灯的个数,也许你没有发现什么,但是亮灯的编号好像看起来有规律呀(是的有规律的)。

更巧妙的解决甚至不用动笔:

前面提到上述亮灯问题等价于求约数个数为奇数的灯的编号。

一个数的约数个数为奇数,这个数有什么特征呢?

我们知道,一个数的约数总是成对存在的。

而一个数的约数的个数为奇数,说明该数一个成对的约数等于同一个数。

即该数是一个数的平方,即该数是一个平方数。

上述问问题: 亮灯问题=》灯的编号的约数为奇数个=》该等的编号是一个平方数。

而 1到100中,平方数有 1^2 = 1, 2^2 = 4, 3^2 = 9, 4^2 = 16, 5^2 = 25,

                                             6^2 = 36, 7^2= 49, 8^2 = 64 9^2 = 81, 10^2 = 100.

故,1到100中有10个平方数 ,亮灯的编号都是这些平方数。

(该题目出自,某不知名培训机构的测试题中)


2. 余数问题:

        有这样一个三位数, 被5余4,被6除余5,被7除余6, 求这个三位数。

 

分析: <1>. 编程解决,计算机最擅长这个,穷举呗。

             <2>. 是否有更好的方法。

编程方案:

#include <stdio.h>#include <stdlib.h>int main(){    int i;    int count = 0;    for(i = 0; i < 1000; ++i) {        if(i % 5== 4 && i % 6 == 5 && i % 7 == 6){            printf("%d, ", i);            ++count;        }    }    printf("\n共有%d个。", count);    return 0;}
计算机结果:


<2>更好方法:不妨令该数为n,有题设可知, n+1 能别 5, 6, 7 同时整除。

n+1 = 5 * 6 *7  *k; (k为整数)

且n+1 为一个三位数,则 100<=n+1 < 1000.

即 100< =210*k < 1000.

所以k= 1, 2, 3, 4, 对应的n为 209, 419, 629,839 。

如果不通过形式化的列举,往往会漏解。说的是三位数,而不是最小的三位数。

可见,形式化的重要性。将问题形式化,能够更好的解决问题。(学学抽象数学,还是哟必要的)。


(该题出现在某知名杀毒软件的笔试题中)。