异或

使用位运算实现int32位 整数的加减乘除

穿精又带淫゛_ 提交于 2020-03-22 22:20:59
3 月,跳不动了?>>> 使用位运算实现int32位 整数的加减乘除 我觉得比较难想的是加法吧。 首先加法,脑海中脑补二进制加法,相同位相加,超过2 ,则进1,留0 那么用位运算怎么实现呢?其实理解了异或和与操作,就很容易想出来了。 我觉得异或操作和与操作完全就是实现加法的。 异或就是相同位相加最后留下的结果,而与就是相同位相加是否进1的结果。 异或:相同位 相同为0,不同为1。 与:相同位 都是1结果才是1,否则都是0。 这不就是二进制相加吗? 异或 与 1+1 = 0 进1 1+0 = 1 进0 0+0= 0 进0 所以加法就是,每次先异或一下,然后算出来进位的结果,再左移一位,因为是进位嘛 static int Add ( int x, int y ) { while (y != 0 ) { int z = x; x ^= y; y &= z; y <<= 1 ; } return x; } 减法,就很容易实现了,减一个数等于加上这个数的负数 一个数怎么变成负数呢?取反码然后+1 所以减法就是 static int Sub ( int x, int y) { int z = Add(~y, 1 ); return Add(x, z); } 那么乘法呢,简单的想法是,一个一个想加呗,a* b不就是b个a相加,对不对,想法的是对的,但是我们要利用二进制的思想,也就倍增的思想。

codechef Chef And Easy Xor Queries

拟墨画扇 提交于 2020-03-22 20:04:14
做法:我们考虑前缀异或和,修改操作就变成了区间[i,n]都异或x 查询操作就变成了:区间[1,x]中有几个k 显然的分块,每个块打一个tag标记表示这个块中所有的元素都异或了tag[x] 然后处理出这个块中每种数的个数 注意查询的时候零散的块要下放标记 代码: #include<bits/stdc++.h> #define N 100005 #define M 334 using namespace std; int cnt[M][N*14],sum[N],tag[M],ll[M],rr[M],a[N]; int n,Q,opt,x,y,block,num; inline int gt(int x){return (x-1)/block+1;} inline void pushdown(int x){ if (!tag[x]) return; for (int i=ll[x];i<=rr[x];i++){ cnt[x][sum[i]]--; sum[i]^=tag[x]; cnt[x][sum[i]]++; } tag[x]=0; } inline void query(int x,int y,int k){ //printf("%d %d\n",gt(x),gt(y)); int ans=0; pushdown(gt(x));pushdown(gt(y)); if (gt(x)

找出数组中两个只出现一次的数字

别说谁变了你拦得住时间么 提交于 2020-03-22 14:55:04
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字 通过这道题感觉位运算很强大~这道题利用异或的几个性质:任何数与其本身异或值都为0,异或运算满足交换律。因此将一组数依次异或,若里面只有一个只出现一次的数,其他的数都出现两次,则最后的结果必然是那个只出现一次的数。要找到两个数字就可以先通过异或整个数组,将得到的结果分组。然后依次安组异或就可以得到所求的值~ 代码如下: #include<iostream> using namespace std; int findFirstOne(int value); bool testBit(int value,int pos); int findNums(int date[],int length,int &num1,int &num2){ if(length<2){return -1;} int ansXor=0; for(int i=0;i<length;i++){ ansXor^=date[i]; //异或 } int pos=findFirstOne(ansXor); num1=num2=0; for(int i=0;i<length;i++){ if(testBit(date[i],pos)) num1^=date[i]; else num2^=date[i]; } return 0;

【算法技巧】位运算装逼指南

江枫思渺然 提交于 2020-03-17 03:03:13
位算法的效率有多快我就不说,不信你可以去用 10 亿个数据模拟一下,今天给大家讲一讲位运算的一些经典例子。不过,最重要的不是看懂了这些例子就好,而是要在以后多去运用位运算这些技巧,当然,采用位运算,也是可以装逼的,不信,你往下看。我会从最简单的讲起,一道比一道难度递增,不过居然是讲技巧,那么也不会太难,相信你分分钟看懂。 判断奇偶数 判断一个数是基于还是偶数,相信很多人都做过,一般的做法的代码如下 if( n % 2) == 01 // n 是个奇数 }   如果把 n 以二进制的形式展示的话,其实我们只需要判断最后一个二进制位是 1 还是 0 就行了,如果是 1 的话,代表是奇数,如果是 0 则代表是偶数,所以采用位运算的方式的话,代码如下: if(n & 1 == 1){ // n 是个奇数。 }    有人可能会说,我们写成 n % 2 的形式,编译器也会自动帮我们优化成位运算啊,这个确实,有些编译器确实会自动帮我们优化。但是,我们自己能够采用位运算的形式写出来,当然更好了。别人看到你的代码,我靠,牛逼啊。无形中还能装下逼,是不是。当然,时间效率也快很多,不信你去测试测试。 2、交换两个数 交换两个数相信很多人天天写过,我也相信你每次都会使用一个额外来变量来辅助交换,例如,我们要交换 x 与 y 值,传统代码如下: int tmp = x; x = y; y = tmp;  

异或(^/XOR)的研究

孤人 提交于 2020-03-16 19:16:37
简介 异或是一种基于二进制的位运算,用符号XOR或者^表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。它与布尔运算的区别在于,当运算符两侧均为1时,布尔运算的结果为1,异或运算的结果为0。 简单理解就是不进位加法,如1+1=0,,0+0=0,1+0=1。 性质 交换律 结合律(即(a^b)^c == a^(b^c)) 对于任何数x,都有x^x=0,x^0=x 自反性 A XOR B XOR B = A XOR 0 = A 应用 异或运算最常见于多项式除法,不过它最重要的性质还是自反性: A XOR B XOR B = A ,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇的性质,利用这个性质,可以获得许多有趣的应用。 例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式 (值) : A=A XOR B (a XOR b) B=B XOR A (b XOR a XOR b = a) A=A XOR B (a XOR b XOR a = b) 类似地,该运算还可以应用在加密,数据传输,校验等等许多领域。 应用举例 1-1000放在含有1001个元素的数组中

关于异或的一些东西和应用

隐身守侯 提交于 2020-03-13 00:48:08
异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。它与布尔运算的区别在于,当运算符两侧均为1时,布尔运算的结果为1,异或运算的结果为0。 简单理解就是不进位加法,如1+1=0,,0+0=0,1+0=1。 性质 1、交换律 2、结合律(即(a^b)^c == a^(b^c)) 3、对于任何数x,都有x^x=0,x^0=x 4、 自反性 A XOR B XOR B = A xor 0 = A 异或运算最常见于多项式除法,不过它最重要的性质还是自反性:A XOR B XOR B = A,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇的性质,利用这个性质,可以获得许多有趣的应用。 例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达式 (值) : A=A XOR B (a XOR b) B=B XOR A (b XOR a XOR b = a) A=A XOR B (a XOR b XOR a = b) 类似地,该运算还可以应用在加密,数据传输,校验等等许多领域。 运用距离: 1-1000放在含有1001个元素的数组中

CodeForces - 617E - XOR and Favorite Number(前缀和+莫队)

我们两清 提交于 2020-03-12 12:07:05
题目链接: https://vjudge.net/problem/CodeForces-617E 题目大意:问题就是给你一个序列,问你询问的区间之内异或和为k的连续区间的数量 如果给的n不大的话,我们可以先考虑前缀和,设a[ ]为区间异或和,如果a[l, r]的异或和等于k,那么a[r]^a[l-1]^k = a[l-1], 如果[1, 1]的异或和为k,那么a[1]^k就等于0,如果[1, 2]的异或和为k,那么a[2]^k等于0, 如果[1, 3]的异或和为k, 那么a[3]^k等 于0, 如果[2, 3]的异或和等于0呢?那它的异或和就等于a[1], 因为a[3]是[1, 3]的异或和, 如果[2, 3]异或k等于0, 那结果就[1, 1],也就是a[1] 但是光用前缀和肯定是不够的,这样的话复杂度会打到O(nm)所以说这时候就要套一个莫队算法了,另外有一个坑点是因为题目是异或所以int可能越界,注意开long long #include<set> #include<map> #include<list> #include<stack> #include<queue> #include<cmath> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<climits>

POJ 3764 The xor-longest Path 解题报告 字典树

巧了我就是萌 提交于 2020-03-10 00:07:30
POJ 3764 The xor-longest Path 解题思路:dfs算出根到每个节点的异或和,再将每个异或和转换为二进制插入到字典树中(从大到小插,因为高位的异或和更大),然后对于每一个询问,尽量选取一条二进制不同的路线就行。参考了别人的代码,注释我加在代码里了,请看。 # include <iostream> # include <math.h> # include <iomanip> # include <algorithm> # include <iostream> # include <math.h> # include <iomanip> # include <algorithm> # include <queue> # include <cstring> # include <string> # include <map> # include <stack> # include <stdio.h> # include <cstdio> # include <stdlib.h> # include <fstream> # include <iomanip> # pragma warning(disable:4996) # define INF 0x3f3f3f3f # define ll long long # define PI acos(-1.0) const

c++位运算

こ雲淡風輕ζ 提交于 2020-03-09 10:14:58
前言 今天准备写一下关于位运算的东西。 其实位运算并没有什么难点,也没有什么太多的内容。 啥也不说了,下面就直接进入文章正文。 初识位运算 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行. 这就是位运算的概念,不难理解吧。 位运算符号 含义 Pascal语言 C/C++语言 Java 按位与 a and b a & b a & b 按位或 a or b a | b a | b 按位异或 a xor b a ^ b a ^ b 按位取反 not a ~a ~a 左移 a shl b a << b a << b 带符号右移 a shr b a >> b a >> b 无符号右移 / / a>>> b 这里各种语言都写在这里了。要用的话就那去吧。 下面说一说位运算符号的具体作用 符号使用方法 按位与 按位与,在c++的表示中为 & 位运算其实只有一种情况,用竖式两位对齐计算。下面是运算结果: 0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1 也就是只有当两个数都是1的时候,按位与的结果才是1 按位或 按位或,在c++的表示中为 | 或运算的四种情况如下: 0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1 按位或就是只要两个数中有一个1的时候,按位或的结果就是1 按位异或(xor)

c++位运算

我们两清 提交于 2020-03-09 10:12:44
前言 今天准备写一下关于位运算的东西。 其实位运算并没有什么难点,也没有什么太多的内容。 啥也不说了,下面就直接进入文章正文。 初识位运算 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行. 这就是位运算的概念,不难理解吧。 位运算符号 含义 Pascal语言 C/C++语言 Java 按位与 a and b a & b a & b 按位或 a or b a | b a | b 按位异或 a xor b a ^ b a ^ b 按位取反 not a ~a ~a 左移 a shl b a << b a << b 带符号右移 a shr b a >> b a >> b 无符号右移 / / a>>> b 这里各种语言都写在这里了。要用的话就那去吧。 下面说一说位运算符号的具体作用 符号使用方法 按位与 按位与,在c++的表示中为 & 位运算其实只有一种情况,用竖式两位对齐计算。下面是运算结果: 0 & 0 = 0 0 & 1 = 0 1 & 0 = 0 1 & 1 = 1 也就是只有当两个数都是1的时候,按位与的结果才是1 按位或 按位或,在c++的表示中为 | 或运算的四种情况如下: 0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1 按位或就是只要两个数中有一个1的时候,按位或的结果就是1 按位异或(xor)