位运算初步入门状态压缩操作
位运算
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。
位运算的用处很多,也很强大。
首先再学习位运算之前,我们先复习以下,编码知识
在计算机中,正数是直接用原码表示的,如5,在计算机中就表示为:0000 0101。
负数用补码表示,如-5,在计算机中表示为1111 1011。
原码 反码 补码问题
原码:将一个整数,转换成二进制,就是其原码。
如:3的二进制是 0000 0011 原码就是0000 0011 -3的原码是 1000 0011
反码:正数的反码就是其原码;负数的反码是将原码中,除符号位以外,每一位取反。
如 3的反码是 0000 0011 -3的反码是 1111 1100
补码:正数的补码就是其原码;负数的反码+1就是补码。
如 3的补码是 0000 0011 -3的补码是1111 1101
位运算:
& 按位与操作
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
3&5 3: 0000 0011
5: 0000 0101
&————————
3&5 0000 0001
| 按位或操作
相同位只要一个为1即为1。
3|5 3: 0000 0011
5: 0000 0101
|————————
3|5: 0000 0111
^按位异或操作
规则:两个数对应位相同 运算结果为0 对应位不同 运算结果为1
3^5 3: 0000 0011
5: 0000 0101
^————————
3^5 0000 0110
性质:异或运算满足结合律和交换律
满足消去律 a^b=b^c 则a=c
a^a=0 (a^b)^b=0
所以 交换两个数的方法可以这么写:
void swap(int a,int b)
{a=a+b;b=a-b;a=a-b;
}
void swap(int a,int b)
{a=a^b;b=a^b;a=a^b;
}
~按位取反
~是一个单目运算符 作用是对二进制每一位数取反
3 0000 0011
~3 1111 1100
*例如 -1在计算机里的补码是 1111 1111
所以 ~(-1)=0000 0000 =0
所以ACM中经常看到 while(~scanf("%d",&a)) 代表 scanf返回-1(即EOF)时结束
<<左移运算符 >>右移运算符
<<左移 按照指定的位数将一个数的二进制数值向左移位 左移后 低位补0 移除的高位舍弃
>>右移 按照指定的位数将一个数的二进制数值向右移位 移除的低位舍弃 如果是无符号数则高位补0 若有符号 则高位补符号或者补0(不同处理器不一样)
如 a=-8 内存中补码为1111 1000
则a>>2=-2 右移两位后为 1111 1110 为-2
状态压缩
这是位运算的一个重要应用
比如 一个迷宫 1代表墙 0代表可以走 通常我们用二维数组存迷宫 做BFS或DFS
那么 迷宫不大的时候 我们可以用二进制数来表示这个迷宫
我们可以把n*m的迷宫 每一行表示为一个m位的二进制数 那么n个整数 就可以表示这个迷宫了
同样的 如果n*m不大的话 我们也可以把整个迷宫 表示为一个n*m位的二进制数
而迷宫的各种操作 我们可以借助位运算来完成 如下表
(切记 位运算的优先级很低! 使用的时候 一定记得带上括号)
去掉最后一位 | (101101->10110) | x >> 1 |
在最后加一个0 | (101101->1011010) | x << 1 |
在最后加一个1 | (101101->1011011) | (x << 1)+1 |
把最后一位变成1 | (101100->101101) | x | 1 |
把最后一位变成0 | (101101->101100) | (x | 1)-1 |
最后一位取反 | (101101->101100) | x ^ 1 |
把右数第k位变成1 | (101001->101101,k=3) | x | (1 << (k-1)) |
把右数第k位变成0 | (101101->101001,k=3) | x & ~(1 << (k-1)) |
右数第k位取反 | (101001->101101,k=3) | x ^ (1 << (k-1)) |
取末k位 | (1101101->1101,k=5) | x & (1 << (k-1)) |
取右数第k位 | (1101101->1,k=4) | (x >> (k-1)) & 1 |
把末k位变成1 | (101001->101111,k=4) | x ^ (1 << (k-1)) |
末k位取反 | (101001->100110,k=4) | x^ (1 << (k-1)) |
把右边连续的1变成0 | (100101111->100100000) | x & (x+1) |
把右起第一个0变成1 | (100101111->100111111) | x | (x+1) |
把右边连续的0变成1 | (11011000->11011111) | x | (x-1) |
取右边连续的1 | (100101111->1111) | (x ^ (x+1)) >> 1 |
位运算初步入门状态压缩操作相关推荐
- 【题解】《算法零基础100讲》(第44讲) 位运算 (位或) 入门
文章目录 一. 概念定义 1.1 位或定义 1.2 位与定义 二. 推荐专栏 三. 相关练习 3.1 根据数字二进制下 1 的数目排序 3.2 二进制表示中质数个计算置位 3.3 2 的幂 一. 概念 ...
- 黑白棋游戏 (BFS + 位运算初步运用)
题目描述 黑白棋游戏的棋盘由4×4方格阵列构成.棋盘的每一方格中放有1枚棋 子,共有8枚白棋子和8枚黑棋子.这16枚棋子的每一种放置方案都构成一个游戏状态.在棋盘上拥有1条公共边的2个方格称为相邻 ...
- 【基本算法】 位运算:二进制状态压缩
二进制状态压缩 二进制状态压缩,是指将一个n位的 bool 数组用 n 位的二进制数表示的方法. OP 运算 取出 n 在二进制表示下的第k位 (n >> k) & 1 取出 n ...
- java 位运算 多个状态_位运算表示对象所处状态
通过一个integer类型属性来表示对象所处的状态: CASE: Invitor:邀请者对象模型 Integer Invitor.joinstatus:邀请者所处参加状态 当前存在状态声明:是否被邀请 ...
- 《算法零基础100讲》(第42讲) 位运算 (位与) 入门
文章目录 零.写在前面 一.概念定义 1.位与的定义 2.位与运算符的简单应用 1)奇偶性判定 2)取末五位 3)消除末尾五位 4)2的幂判定 二.题目描述 三.算法详解 四.源码剖析 五.推荐专栏 ...
- C语言每日一练 —— 第20天:位运算
文章目录 一.前言 二.再谈二进制 1.二进制数值表示 2.二进制加法 3.二进制减法 三.位运算简介 1.位与的定义 2.位与运算符的简单应用 1)奇偶性判定 2)取末五位 3)消除末尾五位 4)2 ...
- python位运算和float浮点型底层存储原理
一 前言 位运算,一个极容易被低端码农忽视的地带,因为它略微需要用一丢丢智商,真的只有那么一丢丢,但高手与low手的差距往往就是长这么一丢丢,能达到的深度就截然不同了 二 真值.机器数(原码.反码.补 ...
- c++ 输出二进制_【位运算与状态压缩】二进制的魅力
[引言] 今天讲讲位运算与状态压缩. 位运算涉及系统底层的运算,骚操作很多:状态压缩则是编程中空间优化的有效手段,应该说两者本身其实并没有太直接的联系,但是在实际使用时会有一定的结合, ...
- 洛谷P1562 还是N皇后(DFS+状态压缩+位运算)
八皇后问题的介绍在此不再赘述,只贴一下经典八皇后问题的实现代码(参考刘汝佳 <算法竞赛入门经典>) void search(int i) {if(i>n){ans++;return; ...
- hdu3006 状态压缩+位运算+hash(小想法题)
题意: 给了n个集合,问你这n个集合可以组合出多少种集合,可以自己,也可以两个,也可以三个....也可以n个集合组在一起. 思路: 是个小想法题目,要用到二进制压缩,位运算, ...
最新文章
- python守护进程进程池_Python进程池非守护进程?
- AutoScaling 弹性伸缩附加与分离RDS实例
- 详细理解java Hibernate 或 JPA的级联操作
- python windows窗口开发_Windows 平台做 Python 开发的最佳组合
- RTree算法及介绍
- 动态规划入门(一)——数字三角形
- c++ windows下declspec
- java jodd_Jodd :一款优雅的 Java 工具集
- achartengine画出动态折线图
- 使用终端shell命令批量改动一个文件下的全部文件的读写权限
- python使用sax实现xml解析
- 渗透杂记-2013-07-13 关于SMB版本的扫描
- C#后台调用跨域MVC服务,带Cookie验证
- DHT 爬虫的学习记录
- 在校大学生如何规划自己的程序员之路
- 当A题成为一种习惯--POJ AC100题纪念贴
- 刀塔霸业怎么在电脑上玩 刀塔霸业电脑版玩法教程
- java中直线距离的计算_java计算两点间的距离方法总结
- XXL之整合SpringBoot
- 关于logcat的使用