編程題目:
66.大廳裏有100盞燈,每盞燈都編了編號,分別爲1-100,每盞燈由一個開關控制。開關按一下燈亮,再按一下燈滅,開關的編號與燈編號一致。開始時燈是全滅的,現在按照以下規則按動開關:
第一次,將所有的燈點亮;
第二次,將所有2的倍數的開關按一下;
第三次,將所有3的倍數的開關按一下;
以此類推,第N次,將所有的N的倍數的開關按一下。
問第N次(N大於等於2,且小於等於100)按完以後,大廳裏還有幾盞燈是亮的。
示例代碼:
package program.calculation.exercise66;
import java.util.Arrays;
/**
* 66.大廳裏有100盞燈,每盞燈都編了編號,分別爲1-100,每盞燈由一個開關控制。開關按一下燈亮,再按一下燈滅,開關的編號與燈編號一致。開始時
* 燈是全滅的,現在按照以下規則按動開關:
* 第一次,將所有的燈點亮;
* 第二次,將所有2的倍數的開關按一下;
* 第三次,將所有3的倍數的開關按一下;
* 以此類推,第N次,將所有的N的倍數的開關按一下。
* 問第N次(N大於等於2,且小於等於100)按完以後,大廳裏還有幾盞燈是亮的。
*/
/**
* 第一種方法:暴力解法
* 分析如下:
* 暴力解法一般是思路上最接近題意的,按題目要求的步驟直接求解,暴力求解一般計算量也是最大的。
*
* 第二種方法:優化解法,轉化爲求[1-100]100個數中,約數個數爲奇數的數,即完全平方數。
* 分析如下:
* 1.對於每盞燈,拉動的次數是奇數時,燈就是亮着的,拉動的次數是偶數時,燈就是關着的。
* 2.每盞燈拉動的次數與它的編號所含約數的個數有關,它的編號有幾個約數,這盞燈就被拉動幾次。
* 3.1-100這100個數中有哪幾個數,約數的個數是奇數。我們知道一個數的約數都是成對出現的,只有完全平方數約數的個數纔是奇數個。
* 所以這100盞燈中有10盞燈是亮着的,它們的編號分別是: 1、4、9、16、25、36、49、64、81、100。
*
*/
public class LightSwitch {
public static void main(String[] args) {
System.out.println("第一種方法(暴力解法):");
countLights1();
System.out.println("第二種方法(優化解法):");
countLights2();
}
//第一種方法:暴力解法
private static void countLights1() {
int count = 0;
int[] state = new int[100]; //100盞燈的狀態
Arrays.fill(state,0); //將100盞燈全部置爲關閉狀態,爲0關閉,爲1點亮
for(int i=1;i<=state.length;i++){ //按動開關次數
for(int j=0;j<state.length;j++){ //100盞燈的編號下標
if((j+1)%i == 0){ //第i次,將所有的i的倍數的開關按一下
if(state[j] == 0){ //原來的狀態取反
state[j] = 1;
}else{
state[j] = 0;
}
}
}
}
System.out.println("大廳裏還亮着的燈的編號是:");
for(int i=0;i<state.length;i++){
if(state[i] == 1){
count++;
System.out.print((i+1)+" ");
}
}
System.out.println("\n共有"+count+"盞燈");
}
//第二種方法:優化解法,轉化爲求[1-100]100個數中,約數個數爲奇數的數,即完全平方數.
private static void countLights2() {
int count = 0;
int[] lights = new int[100];
System.out.println("大廳裏還亮着的燈的編號是:");
for(int i=0;i<lights.length;i++){
lights[i] = i+1;
//求lights[i]的平方根(double),並轉換成int類型
int n = (int) Math.sqrt(lights[i]);
//如果lights[i]平方根的平方等於lights[i],即爲完全平方數
if(lights[i] == n*n){
count++;
System.out.print(lights[i]+" ");
}
}
System.out.println("\n共有"+count+"盞燈");
}
}