利用二进制枚举

本文介绍了位运算的基本概念及其应用,并通过实例详细解释了如何使用二进制进行枚举,包括位运算符的使用方法及左移、右移操作的应用。

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

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

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

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

  • 与运算:两者都为 1时,结果即为1,否则为0。--有0出0
  • 或运算:两者都为 00时,结果即为0,否则为1。--有1出1
  • 异或运算:是两者同为 01 时,结果即为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; // 记录合法方案数
		    }
		}
	}

}




### 关于蓝桥杯中的二进制枚举蓝桥杯竞赛中,二进制枚举是一种常见的算法技巧,用于处理组合问题或状态表示。通过将问题的状态映射到二进制数位上,可以高效地遍历所有可能的组合情况。 #### 什么是二进制枚举二进制枚举是指利用二进制数来表示集合中的元素是否存在的一种技术。假设有一个大小为 \( n \) 的集合,则可以通过长度为 \( n \) 的二进制字符串来唯一表示该集合的所有子集。例如,当 \( n=3 \),则可以用三位二进制数 `000` 到 `111` 来表示所有的子集[^1]。 #### 蓝桥杯中的典型应用 以下是几个典型的例子以及其对应的解题思路: 1. **灯泡开关问题** 假设有若干盏灯,每盏灯有开和关两种状态。给定一系列操作指令,要求计算最终哪些灯处于开启状态。 解题思路: 使用一个整数变量存储当前灯的状态,每一位代表一盏灯的状态(0 表示关闭,1 表示打开)。每次执行操作时,只需对该整数进行按位异或运算即可完成状态更新[^2]。 ```python # 初始化灯的状态 state = 0 # 执行多次翻转操作 operations = [1, 3, 5] # 假设这些位置上的灯被翻转 for pos in operations: state ^= (1 << (pos - 1)) # 更新对应位置的状态 # 输出最终状态 result = [] for i in range(8): # 假设有8盏灯 if state & (1 << i): result.append(i + 1) print(result) ``` 2. **物品选取问题** 给定一组物品及其价值,问最多可以选择多少种不同的方案使得总重量不超过某个上限。 解题思路: 枚举所有可能的选择方式,并判断是否满足条件。由于选择与否可以直接用二进制位表示,因此可以快速实现暴力搜索[^4]。 ```python from itertools import combinations weights = [2, 3, 5, 7] max_weight = 10 count = 0 n = len(weights) for mask in range(1 << n): total = sum(w for i, w in enumerate(weights) if mask & (1 << i)) if total <= max_weight: count += 1 print(count) ``` 3. **路径规划问题** 在某些情况下,需要找到一条经过特定节点序列的有效路径。此时也可以借助二进制编码记录访问过的节点集合。 解题思路: 定义动态规划数组 dp[mask][node],其中 mask 是已访问节点的集合,而 node 当前所在的位置。转移方程基于邻接关系构建[^3]。 --- ### 总结 上述方法展示了如何运用二进制枚举解决实际编程比赛中的复杂场景。它不仅简化了逻辑表达,还提高了程序运行效率,在时间允许范围内能够穷尽各种可能性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obession

觉得有用可以打赏咖啡一杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值