转载 利用二进制枚举

用二进制的一位表示集合对应某一元素的选取状态,1 表示选取,0 表示未选取;

----------------------------------------------------------------------------------------------------------

先介绍位运算:位运算是对二进制的每一位进行计算,所以每一位只有 0或 1两种可能

三种常用的位运算符:与&、或|、异或^;

  • 与运算:两者都为 1时,结果即为1,否则为0。--有0出0
  • 或运算:两者都为 00时,结果即为0,否则为1。--有1出1
  • 异或运算:是两者同为 0 或1 时,结果即为0,否则为1。相同出1 ,相异出0;

位运算符中有两种操作,左移<<和右移>>

对于A << B,表示把A转化为二进制后向左移动B位(在末尾添加B0)。

对于A >> B,表示把A转化为二进制后向右移动B位(删除末尾的B位)。

如2<<2 就是二进制的10左移2位:二进制的1000 转为10进制为8;

这里也看的出来2<<2 就是 2*(2的二次方);2<<3就是2*(2的三次方);

面试题:用最有效率的方法算出2乘以8等於几? 

2 << 3,

因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3

题目:

对于一个数的二进制表示,交换其高低位顺序。比如,对于整数 
123523532123523532
123523532 的二进制表示:

00000111 01011100 11010001 11001100

交换后的结果为
11001100 11010001 01011100 00000111

import java.util.Scanner;
 
class Main {
	public static void print(long x) {
		for (int i = 31; i >= 0; --i) {
	        if ((x&(1L<<i)) > 0) System.out.print("1");
	        else System.out.print("0");
	        if (i % 8 == 0) {
	            if (i > 0) System.out.print(" ");
	            else System.out.print("\n");
	        }
	    }
	}
 
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		long x = scanner.nextLong();
        long mask = (1L<<32)-1;//1左移得到10000..... 然后-1 得到1111.......
		
		print(x);
        x=((x<<24)&mask)+((x>>24)&mask)+((x<<8)&0x00FF0000)+((x>>8)&0X0000FF00);//可以用&上1或者0来得到或者删除相应位的数字;
		print(x);
	}
}

----------------------------------------------------------------------------------------------------------

位运算介绍完了 看如何用二进制枚举:

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 

请你计算李白遇到店和花的次序,可以把遇店记为1,遇花记为0。

public class 李白打酒二进制 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int ans = 0;
		for (int i = 0; i < (1<<14); ++i) {
		    int tot_1 = 0;
		    int tot_0 = 0;
		    int num = 2;
		    for (int j = 0; j < 14; ++j) {//从0开始,到13,一共14位;查看每一位是0还是1
		    	//j为0时,i&1-->查看的第一位;j为1时i&10-->查看第二位...以此类推
		        if ((i&(1<<j))==1) { // 这里判断二进制 i 从右数第 j + 1 位是否为 1
		            tot_1++;
		            num = num * 2;
		        } else {
		            tot_0++;
		            num = num - 1;
		        }  
		    }
		    if (tot_1 == 5 && tot_0 == 9 && num == 1) {
		        ++ans; // 记录合法方案数
		    }
		}
	}
 
}

猜你喜欢

转载自blog.csdn.net/k_koris/article/details/82315413