# 位运算_1 2016.6.3

http://www.matrix67.com/blog/archives/263

http://www.matrix67.com/blog/archives/264

%%%Matrix67

1、位运算符号

a & b 位与

a | b 位或

a ^ b 位异或

~a 位取反

a << b 位左移

a >> b 位右移

2、位运算的使用

（1）& 运算

①屏蔽

②测0

if (N & 1) {
printf("N is an odd\n");
} else {
printf("N is an even\n");
}

（2）| 运算

（3）^ 运算

①位求反

②相等比较

1314520 xor 19960112 = 19177448，我就把 19177448 告诉 MM

MM 再次计算 19177448 xor 19960112 的值，得到 1314520，于是她就明白了我的企图

③交换两个变量的值

（4）~运算

typedef unsigned int uint;

uint N = 100;
N = ~N;
printf("%u\n", N);

//Result : 4294967195

（5）<< 运算

（6）>> 运算

Matrix67大牛博客的那个例题的链接失效了

CodeForces_677C Vanya and Label

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;

const int mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e5 + 10;
int num[300];
char s[maxn];
int _0_num[70];

int Count_0(int n);

int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
for (int i = '0'; i <= '9'; ++i) {
num[i] = i - '0';
}
for (int i = 'A'; i <= 'Z'; ++i) {
num[i] = i - 'A' + 10;
}
for (int i = 'a'; i <= 'z'; ++i) {
num[i] = i - 'a' + 36;
}
num['-'] = 62;
num['_'] = 63;
for (int i = 0; i < 64; ++i) {
_0_num[i] = Count_0(i);
}
gets(s);
int len = strlen(s);
ll ans = 1;
for (int i = 0; i < len; ++i) {
int t1 = num[(int)s[i]];
int t2 = _0_num[t1];
if (t2 != 1) {
ans = (ans * t2) % mod;
}
}
printf("%I64d\n", ans);
return 0;
}

int Count_0(int n)
{
int ret = 1;
int num = 6;
while (num--) {
if ((n&1) == 0) {
ret *= 3;
}
n >>= 1;
}
return ret;
}

⒈去掉最后一位               >> 1

⒉在最后加一个0            << 1

⒊在最后加一个1            (<< 1) + 1

⒋把最后一位变为1        | 1

⒌把最后一位变为0        (| 1) - 1
⒍最后一位取反              ^ 1

⒎右数第 k 位变为1       | (1 << (k - 1))

⒏右数第 k 位变为0       & (~(1 << (k - 1)))
⒐右数第 k 位取反         ^ (1 << (k - 1))

⒑取末三位                     & 7

⒒取末 k 位                     & ((1 << k) - 1)

⒓取右数第 k 位             (>> ( k - 1)) & 1

⒔把末 k 位变为1           | ((1 << k) - 1)

⒕末 k 位取反                 ^ ((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

⒚去掉右起第一个 1 的左边         (100101000 -> 1000)                 x & (x ^ (x - 1))

-x 实际上是 x 按位取反，末尾加 1 以后的结果

388288 = 1001010110010000

-388288 = 0110101001110000

3、二进制位中的1有奇数个还是偶数个

int Judge(int n)    //二进制中 1 的个数的奇偶性，奇数返回 1，偶数返回 0
{
int ret = 0;
while (n) {
if (n & 1) {
ret += 1;
}
n >>= 1;
}
if (ret & 1) {
return 1;
}
return 0;
}

int Judge(int n)    //二进制中 1 的个数的奇偶性，奇数返回 1，偶数返回 0
{
n ^= (n >> 1);
n ^= (n >> 2);
n ^= (n >> 4);
n ^= (n >> 8);
n ^= (n >> 16);
if (n & 1) {
return 1;
}
return 0;
}

1314520的二进制为101000000111011011000

00000000000101000000111011011000
xor       0000000000010100000011101101100
—————————————————————
00000000000111100000100110110100

00000000000111100000100110110100
xor       000000000001111000001001101101
—————————————————————
00000000000110011000101111011001

4、计算二进制中的 1 的个数

int Count_1(int x)    //计算二进制中 1 的个数
{
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF);
return x;
}

+—+—+—+—+—+—+—+—+
| 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 |   <—原数
+—+—+—+—+—+—+—+—+
|  1 0  |  0 1  |  0 0  |  1 0  |   <—第一次运算后
+——-+——-+——-+——-+
|    0 0 1 1    |    0 0 1 0    |   <—第二次运算后
+—————+—————+
|        0 0 0 0 0 1 0 1        |   <—第三次运算后，得数为5
+——————————-+

5、二分查找32位整数的前导0个数

int Count_Pre0(unsigned int x)    //二分查找 32 位整数的前导 0 的个数
{
if (x == 0) {
return 32;
}
int n = 1;
if ((x >> 16) == 0) {
n += 16; x <<= 16;
}
if ((x >> 24) == 0) {
n += 8; x <<= 8;
}
if ((x >> 28) == 0) {
n += 4; x <<= 4;
}
if ((x >> 30) == 0) {
n += 2; x <<= 2;
}
n -= (x >> 31);
return n;
}

Vijos 1201 高低位交换（Matrix67原创）

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>

using namespace std;

typedef unsigned int uint;

int main()
{
uint n;
scanf("%u", &n);
n = (n << 16) | (n >> 16);
printf("%u\n", n);
return 0;
}

• 本文已收录于以下专栏：

## 位运算_1

• qq_18455665
• 2015年12月09日 16:21
• 716

## 位运算--统计一个数的二进制序列中1的个数

• peiyao456
• 2016年06月21日 00:16
• 1564

## 位运算 详解 技巧

• cFarmerReally
• 2017年01月28日 18:16
• 535

## 位运算之判断奇偶性&1

• Acceptee
• 2017年03月03日 14:37
• 875

## 二分查找位运算——32位整数中寻找第一个为1的位

• syzcch
• 2012年12月13日 09:47
• 3279

## 位运算--求一个 数二进制中1的个数

1.五种位运算：（1）&(与)–有0则0；无0则1； （2）|（或）–有1则1，无1则0； （3）^（亦或）–相同为0，不同为1； （4）>>右移（最右边的位被抛弃） 正数，最左边...
• gogogo_sky
• 2017年05月10日 16:50
• 189

## 【位运算】实现加减乘除、取最高位1

• brandohero
• 2014年09月27日 10:25
• 1642

## 2016.6.3

1.深搜 生日蛋糕 2.棋盘问题
• pku_15120
• 2016年06月03日 14:36
• 84

## C++位运算设置指定位为0或1

• lgh1700
• 2012年07月03日 23:12
• 4091

## 位运算（2）-- 集合中的位运算

• xushao_Movens
• 2016年08月13日 14:24
• 471

举报原因： 您举报文章：位运算_1 2016.6.3 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)