n盏灯亮灭问题

      前几天看了华为的一个上机操作题,讲得是n盏灯亮灭问题,本质上还是数学问题,感觉很有趣,和大家分享一下,问题描述如下:

      有n盏灯排成一排,依次标号1,2,…,n,每盏灯都有一根拉线开关,最初电灯都是关着的.现有n个人,都沿着电灯路线走过,第一个人走过时,把凡是号码是1的倍数的灯的开关拉一下;接着第二个人走过时,把凡是号码是2的倍数的灯的开关拉一下;第三个走过时,把凡是号码是3的倍数的灯的开关拉一下;…;最后,第n个人走过时,把最后那盏灯的开关拉一下,问:最后有几盏灯是亮着的?

这个问题本质是求某一整数的因数个数的奇偶性问题,因数个数为偶数的标号为n的灯最终灭,因数个数为奇数的标号为n的灯最终亮,回忆我们学过的数学知识,只有完全平方数的因数的个数才是奇数,例如4,9,16........

     当时我的第一想法是设置一个空间大小为n的数组,里面依次存储1—n每个数的因数的个数,然后循环判断这个数组中奇数的个数,从而计算出最后的结果,代码就不贴了。后来在网上看到了另一种解法,这种解法中是建立一个bool组,设开始每盏灯都是灭的,每有一个因数就执行开或者关操作,也就是非操作,最后统计下bool组中有多少个是0的,就是亮灯的盏数。这个解法很好的,计算量比我的第一想法要省很多。可见代码是可以逐步优化的。代码如下:

#include<iostream>

using namespace std;

int main()

{    bool form[1001];

    int n,count=0,i;

        cin>>n;

    for(i=1;i<=n;i++)

    {    for(int j=i;j<=n;j++)

        {    if(j%i==0)

                form[j]=!form[j];

        }

    }

    for(i=1;i<=n;i++)

    {     if(form[i]==0)

         count++;

    }

    cout<<""<<count<<" 盏灯是亮着的。"<<endl;

 return 0;

}

 其实经过我们最上面的分析,只要找出N内所有的完全平方数,算出个数就可以了,可以一步到位啊,省事又省心。如下的小程序:

#include <iostream>

#include<math.h>

using namespace std;



int main()

{   int count=0,n;

    double i;

    cin>>n;

    for(i=1;i<=n;i++)

    {

        if(int(sqrt(i))==sqrt(i))

            count=count+1;

    }

    cout<<count<<endl;

    return 0;

}

从这道题的解法可以看出来,算法可以一步步优化,代码也可以一步一步改进的。

你可能感兴趣的:(问题)