首页 > 代码库 > 华为机试(7)

华为机试(7)

中级题:100分
描述:一条长廊里依次装有n(1 ≤ n ≤ 65535)盏电灯,从头到尾编号1、2、3、…n-1、n。每盏电灯由一个拉线开关控制。开始,电灯全部关着。 
有n个学生从长廊穿过。第一个学生把号码凡是1的倍数的电灯的开关拉一下;接着第二个学生把号码凡是2的倍数的电灯的开关拉一下;接着第三个学生把号码凡是3的倍数的电灯的开关拉一下;如此继续下去,最后第n个学生把号码凡是n的倍数的电灯的开关拉一下。n个学生按此规定走完后,长廊里电灯有几盏亮着。注:电灯数和学生数一致。 

 
输入:电灯的数量 
输出:亮着的电灯数量 
样例输入:3  ,样例输出:1 


解题思路1:这道题,如果要模拟的话,当然是可以的,但对于代码基础较差的同学写起来就比较吃力了,在这里写模拟的做法  
解题思路2:在这道题上面多思考思考,可以看出,对于任何一个灯来说,比如12,其因数有1,2,3,4,6,12。说明,编号为1,2,3,4,6,12的学生分别要拉它一下,在这里发现,1*12=12,2*6=12,3*4=12,所以其因数都是一一对应的,也就是,1拉的那一下被12抵消了,2拉的那一下被6抵消了,那么谁不会被抵消呢?答案是平方数,比如9的因数是1,3,9,那么3*3=9,而3只拉一次,所以不会被抵消。因此,这道题的答案就是,输入的n以内的平方数个数,等于(int)sqrt(n)。 
从这道题可以看出,编程的很多时候,多思考比多动笔要有用的多。  

#include<iostream>using namespace std;void main(){    int n;    cin>>n;    int numLightOn = 0;    for(int i=1;(i*i)<=n;i++)       numLightOn++;    cout<<numLightOn<<endl;  }

用模拟的方法代码如下:

#include<iostream>#include<vector>using namespace std;void main(){    int n;    cin>>n;    vector<int> light(n+1,0);//0表示灭的,1表示亮的    int numLightOn=0;    for(int i=1;i<=n;i++)//n个人    {       int j=i;       int times = 2;       while(j<=n)       {         light[j]= 1-light[j]; // 0->1,1->0         j = i;    //第j盏灯         j *= times;         times++;              }    }//end for    for(int i=1;i<=n;i++)    {       if(light[i]==1)         numLightOn++;    }    cout<<numLightOn<<endl;    }