现在的位置: 首页 > 综合 > 正文

从开关灯到位运算

2018年05月28日 ⁄ 综合 ⁄ 共 1285字 ⁄ 字号 评论关闭

问题:

 

大厅里有64盏灯,每盏灯都编了号码,分别为1-64。每盏灯都由一个开关来控制。(开关按一下,灯亮,再按一下灯灭。开关的编号与被控制的灯相同。)开始时,灯是全灭的。现在按照以下规则按动开关。
第一次,将所有的灯点亮。
第二次,将所有2的倍数的开关按一下。
第三次,将所有3的倍数的开关按一下。
以此类推。第N次,将所有N的倍数的开关按一下。
问第N次(N小于等于64)按完以后,大厅里还有几盏灯是亮的。

 

package com.phj.math;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class LightTest {

public static void main(String[] args) {

int max = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
try {
System.out.println("请输入灭灯的盏数(0< X <=64):");
max = Integer.parseInt(br.readLine());
} catch (Exception e) {
System.err.println(e.getMessage());
}
long light = 0;
for (int n = 1; n <= max; n++) {
for (int i = 1; i <= 64; i++) {
// i代表了灯/开关的编号,需要将n的倍数所在的位取反
// 比如:n=1,那么,需要将1,2,3,4,5...这些位取反
// n=2,需再将2,4,6,8,10...这些位取反
// n=3,需再将3,6,9,12,15...这些位取反
if (i % n == 0) {
// 将i那一位取反
// 如何将某一位取反呢?没有直接将某一位取反的现成的操作,
// 那么,我们可以判断此位的值是1还是0,然后据此,将此位改成0或1
// 接下来的问题就是如何判断某位的值?如何将此为改成0或1?

long temp = 1;
temp = temp << (i - 1);
if ((temp & light) == 0) { // 表示i这一位为0
// 需将此位改成1
light = light | temp;
} else { // 表示i这一位为1
// 需将此位改成0
temp = ~temp;
light = light & temp;
}
}
}
}

// 现在的light值,在某一位上如果取值为0表示灯灭,某一位上如果取值为1表示灯亮
// 下面输出结果
int total = 0; // 总共亮灯的数量
for (int i = 0; i < 64; i++) {
long temp = 1;
temp = temp << i;
temp = temp & light;
if (temp == 0) { // 灯灭
System.out.println("【" + (i + 1) + "】号灯:灭");
} else { // 灯亮
System.out.println("【" + (i + 1) + "】号灯:亮");
total = total + 1;
}
}
System.out.println("在经过【" + max + "】次之后,总共有【" + total + "】盏灯是亮的!");
}

}

抱歉!评论已关闭.