异或

异或算法

橙三吉。 提交于 2020-01-24 02:49:00
最近碰到很多通过巧妙着运用 位运算 来巧妙解决复杂问题的算法,今天分享的这道题,或许能够开拓你的一些算法思维。 题目描述 有一组存放 ID 的数据。并且 ID 取值为 0 - (N-1) 之间,其中只有一个 ID 出现的次数为 1,其他的 ID 出现的次数都等于 2,问如何找到这个次数为 1 的 ID ? 解法一:巧用数组下标 不知道有多少人还记得我之前分享的 巧用数组下标 的技巧: 一些常用的算法技巧总结 。 我的第一想法便是采用 下标法 来解决,把 ID 作为数组 arr 的下标,在遍历 ID 的过程中,用数组记下每个 ID 出现的次数,即每次遍历到 ID = n,则 arr[n]++。 之后我们在遍历数组 arr,找到 arr[n] = 1 的ID,该下标 n 便是我们要寻找的目的 ID。 这种方法的时间复杂度为 O(N),空间复杂度为 O(N)。 解法二:巧用哈希表 显然时间复杂度是无法再降低的了,因为我们必须要遍历所有的 ID,所以时间复杂度最少都得为 O(N)了,所以我们要想办法降低空间复杂度。 大家想一个问题,假如我们检测到某个 ID 已经出现了 2 次了,那么这个 ID 的数据我们还需要存储记录吗?大部分的 ID 都出现了 2 次,这一大部分的数据真的需要存储吗? 答是不用的,因为出现 2 次的 ID 不是我们所要找的。所以我们可以优化 解法一 ,我们可以采用

计算机网络数据链路层:海明码的工作流程

无人久伴 提交于 2020-01-22 06:20:04
在上一节我们讲到了数据链路层差错控制中用于检测的冗余编码,这一节我们来看看用于纠错的海明码。这一节我们主要用一个例子看看海明码是如何工作的。 假如发送一段二进制信息码为101101,现加上海明码来用其纠错 第一步:确定校验码位数r 具体有多少位校验码取决于一个海明不等式: 2^r>=k+r+1 其中k为二进制信息吗的位数。 在这段数据中,k=6,我们暂且把它们从左至右标号a1,a2……a6。所以满足不等式的r值为4,也就是四位校验码,我们为它们编号r1、r2……r6。 第二步:确定校验码和数据的位置及校验码值 我们用一个表格形象地说明这个问题: 先在表格中插入校验码,插入校验码的方法是:r1插在2 0位置中……r n插在2^(n-1)位置中。然后再将数据位按从左到右的顺序插入剩余的空位: 那么如何确定各个已经确定好编号位的具体二进制值呢?我们先将数据位的值插入对应编号的下方 然后看看这些冗余检验码可以检验哪些位,具体是这样做的: 把各个位数对应的二进制码写进表格的对应位置,然后再看检验码对应的二进制位数上,哪一位是“1”,那么这个校验码就可以参与到这一位为“1”的二进制位数对应的数据的校验工作。比如r1的第四位为“1”,那么它可以负责a1、a2、a4、a5的校验工作,现将r1、a1、a2、a4、a5提出从左至右进行异或运算,令等式等于0,解方程获得r1的具体值。 r1 xor a1

两区间异或和最大

谁说我不能喝 提交于 2020-01-21 19:19:21
https://blog.csdn.net/zuzhiang/article/details/79877109 题意:给xi你 n 个数,让你求两个不相交的区间元素异或后的和的最大值。本题中 n 的上限是 4*10^5. 解法:求出前缀异或和和后缀异或和,dp【i】表示前i个数任意区间的最大异或和。 根据性质异或和性质dp【i】异或dp【j】相同部分会抵消,可以根据递推求出dp【i】 转化为dp【i-1】+ suf【i】最大值,可以防止区间重叠。 #include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n

只出现一次的数字

冷暖自知 提交于 2020-01-21 00:23:44
给定一个 非空 整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 分析: 相同的数字异或为0,0与任何数字异或为本身,所以对所有数字进行异或,一定得到单独的数字 class Solution { public: int singleNumber(vector<int>& nums) { // 相同的数字通过异或为0,0与任何数字异或是自己,所以只需要对所有数字进行异或就可以了 int result = 0; for(int num:nums){ result ^= num; } return result; } }; 来源: CSDN 作者: Random_r 链接: https://blog.csdn.net/Random_R/article/details/104053477

第十八节:MySQL中的运算符

梦想的初衷 提交于 2020-01-20 17:49:53
MySQL 支持 4 种运算符: 算术运算符:包括加、减、乘、除等,用来执行算术运算 比较运算符:包括大于、小于、in或者not null等等。主要用于数值的比较、字符串的匹配等方面 逻辑运算符:包括与、或、非和异或等逻辑运算符。其返回值为布尔型,真值(1 或 true)和假值(0 或 false) 位运算符:包括按位与、按位或、按位取反、按位异或、按位左移和按位右移等位运算符。位运算必须先将数据转换为二进制,然后在二进制格式下进行运算,最后将二进制的值转换为原来的类型 算术运算符 语法格式:表达式1 算术运算符 表达式2 实例: select id/2 from Teacher; select id*2; MySQL 中的算术运算符如下: 算术运算符 说明 + 加法运算 - 减法运算 * 乘法运算 / 除法运算,返回商 % 求余运算,返回余数 比较运算符 语法:表达式1 比较运算符 表达式2 MySQL 中的比价运算符如下: 比较运算符 说明 = 等于 < 小于 <= 小于等于 > 大于 >= 大于等于 <=> 安全的等于,不会返回 UNKNOWN <> 或!= 不等于 IS NULL 或 ISNULL 判断一个值是否为 NULL IS NOT NULL 判断一个值是否不为 NULL LEAST 当有两个或多个参数时,返回最小值 GREATEST 当有两个或多个参数时,返回最大值

题解【bzoj1954 Pku3764 The xor – longest Path】

心已入冬 提交于 2020-01-20 10:44:41
做该题之前,至少要先会做 这道题 。 记 \(d[u]\) 表示 \(1\) 到 \(u\) 简单路径的异或和,该数组可以通过一次遍历求得。 \(~\) 考虑 \(u\) 到 \(v\) 简单路径的异或和该怎么求? 令 \(z=\operatorname{lca}(u,v)\) ,则 \(u\) 到 \(v\) 简单路径的异或和可以分成两段求解:一段是 \(z\) 到 \(u\) 简单路径的异或和,一段是 \(z\) 到 \(v\) 简单路径的异或和,二者异或一下即为 \(u\) 到 \(v\) 简单路径的异或和。 由于异或 " \(a \operatorname{xor} a=0\) " 的性质,两条路径重叠的部分异或起来即为 \(0\) ,可得 ​ \(z\) 到 \(v\) 简单路径的异或和为 \[ d[u] \operatorname{xor} d[z] \] ​ \(z\) 到 \(v\) 简单路径的异或和为 \[ d[v] \operatorname{xor} d[z] \] 进一步,可得 ​ \(u\) 到 \(v\) 简单路径的异或和为 \[ (d[u]\operatorname{xor}d[z])\operatorname{xor}(d[v]\operatorname{xor}d[z]) \] ​ 由于异或满足交换律,可化简为 \[ d[u]

leetcode_136. 只出现一次的数字

徘徊边缘 提交于 2020-01-20 03:54:16
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 解析: 使用异或位运算,相同的数字异或会变成0,全部异或之后剩下的数字便是答案 class Solution { public : int singleNumber ( vector < int > & nums ) { int n = nums . size ( ) ; int a = nums [ 0 ] ; for ( int i = 1 ; i < n ; i ++ ) { a = a ^ nums [ i ] ; } return a ; } } ; 来源: CSDN 作者: 二次元憨批 链接: https://blog.csdn.net/qq_37292201/article/details/104042355

bzoj4561: [JLoi2016]圆的异或并

六眼飞鱼酱① 提交于 2020-01-18 22:18:04
https://www.lydsy.com/JudgeOnline/problem.php?id=4561 hdu3511 变式 https://www.cnblogs.com/TheRoadToTheGold/p/12209904.html 层次为奇数的加,偶数的减 #include<set> #include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 200001 int line; struct Line { int id,xi; }e[N<<1]; int lev[N]; bool equal(double a,double b) { return abs(a-b)<1e-7; } struct Circle { int x,y,r; double gety(int f) { double dy=sqrt(1.0*r*r-1.0*(line-x)*(line-x)); return y+dy*f; } }cir[N]; struct Node { int id,tag; Node(){} Node(int id_,int tag_) : id(id_),tag(tag_) {} bool operator < (const

AcWing 891 Nim游戏

南楼画角 提交于 2020-01-18 08:16:06
题目描述: 给定n堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。问如果两人都采用最优策略,先手是否必胜。 输入格式 第一行包含整数n。第二行包含n个数字,其中第 i 个数字表示第 i堆石子的数量。 输出格式 如果先手方必胜,则输出“Yes”。否则,输出“No”。 数据范围 1≤n≤10^5,1≤每堆石子数≤10^9 输入样例: 2 2 3 输出样例: Yes 分析: 先给出Nim游戏的一些概念和结论: 给定N堆物品,第i堆物品有Ai个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。 我们把这种游戏称为NIM博弈。把游戏过程中面临的状态称为局面。整局游戏第一个行动的称为先手,第二个行动的称为后手。若在某一局面下无论采取何种行动,都会输掉游戏,则称该局面必败。 所谓采取最优策略是指,若在某一局面下存在某种行动,使得行动后对面面临必败局面,则优先采取该行动。同时,这样的局面被称为必胜。我们讨论的博弈问题一般都只考虑理想情况,即两人均无失误,都采取最优策略行动时游戏的结果。 NIM博弈不存在平局,只有先手必胜和先手必败两种情况。 定理: NIM博弈先手必胜,当且仅当 A1 ^ A2 ^ … ^ An != 0

java中异或运算的应用

天涯浪子 提交于 2020-01-17 21:48:24
java中异或运算(^)的应用 异或运算法则   1. a ^ b = b ^ a   2. a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;   3. d = a ^ b ^ c 可以推出 a = d ^ b ^ c.   4. a ^ b ^ a = b. 异或运算   1、异或是一个数学运算符。应用于逻辑运算。   2、例如:真异或假的结果是真,假异或真的结果也是真,真异或真的结果是假,假异或假的结果是假。就是说两个值相 异结果为真。   异或的运算方法是一个二进制运算:   1^1=0   0^0=0   1^0=1   0^1=1   两者相等为0,不等为1. 总之,就是这样,n^0=n n^n=0,即任何数与0进行异或,为它本身,两个相同的数进行异或运算,会得到0。     前几天看到一个这样的题目,对于一个有多个数值的数组,只有一个是唯一的,其他都是成对的,怎样快速找到这个唯一值。在我没听过异或运算的时候,真是一脸懵,但是后来在看hashMap源码的时候看到了^ 异或运算符,搜了一下,才发现曾经看到的这道题的解题,顿时豁然开朗。 int[] numarry = new int[]{1,2,3,2,3}; int aim = numarry[0]; for(int i = 1; i < 5; i++) { aim = aim ^