异或

JZOJ5373【NOIP2017提高A组模拟9.17】信仰是为了虚无之人

你。 提交于 2020-04-05 20:52:09
题目 分析 我们发现,如果[l,r]的异或和为k是真要求,有且仅当不存在[l,i]和[i,r]两个区间的异或和不为k。 我们用带权并查集了维护这些,但是,由于区间不连续,我们将点权移到边上,对于区间[l,r]的点权异或和,变成[l,r+1]边权异或和。并查集合并时将大点连向小点, 最后通过并查集求异或点缀和,如果某个点没有限制,值为零。 #include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> #include <map> const int maxlongint=2147483647; const int mo=1e9+7; const int N=200005; using namespace std; int b[N*2][3],fa[N],v[N],n,m,czy,ans,tot,sum[N],la[N*2],ne[N*2],vv[N*2],to[N*2]; int get(int x) { if(x==fa[x]) return x; int y=get(fa[x]); v[x]^=v[fa[x]]; return fa[x]=y; } int main() {

脚本编程(一)

∥☆過路亽.° 提交于 2020-04-05 19:33:05
脚本编程(一) 啰里啰唆:每周的最后一天都特别难受。墨迹扣不出文章。 一、概况 注释是以 # 开都的, # 开头不一定都是注释 SHELL 是解释型语言 SHELL 脚本第一句以 #!/bin/bash 开头 SHELL 脚本需要具有执行权限 一般以 .sh 结尾 别名在脚本中无效。在脚本中不能使用别名。 bash 使用技巧: -n 检查语法 , 无法无法检测处命令错误,同时只是检查语法不会真正执行脚本。 -x 逐行执行,逐行显示执行结果 脚本中的错误: 1 、语法错误,会导致后续的命令无法继续执行。可以通过 bash -n 选项来检查 提示的错误行不一定是准确的。 2 、命令错误,后续的命令还可以继续执行。无法通过 bash -n 选项来检查错误,可以使用 set -e 或者 set -o errexit 来设定遇到错误命令后退出 3 、逻辑错误,只能使用 bash -x 选项来检查错误。 变量: 变量表示命名的内存空间,讲数据放在内存空间中,通过 "$ 变量名 " 引用 , 从而获取数据 内置环境变量: PS1 SHELL HASTNAME $$ $? 自定义变量: [set] NAME=VALUE set 可以省略 变量类型: 字符型:默认都是字符型 数值:整型、 bash 不支持浮点型 静态编译语言,使用变量前,先声明变量类型,之后类型不能改变,在编译时执行检查, JAVA

带修改线性基

痞子三分冷 提交于 2020-04-03 23:57:48
最近模拟赛中有带修线性基这个我 (闻所未闻 见所未见)是我的消息太不灵通了么 的黑科技。 我们仍未知道那天所见到的黑科技的名字 这道例题是动态加边 每次询问一个独立集的最大权值。这里的权值定义为题目中的定义。 对于前两个测试点 暴力枚举选出了哪些点 然后判断哪些边可以用 通过这个暴力的操作可以发现 将边的权值异或到点上 最后用点进行异或即可将那些不能使用的边给异或掉。 于是可以发现这是一个选出若干个点使异或和最大的题目->线性基的题目。 观察3,4,5测试点 无自环呈若干个联通块状 每个连通块最多只有一条边 点权不带修改 动态加入权值的线性基的题目。 剩下的测试点其实是 每次有两个点的权值变化 在线维护线性基。 对于这种问题 一种比较粗暴的方法 是直接上线段树分治维护线性基 记录一下每次权值插入的线性基的位置然后方便撤销。 复杂度 \(mlog^2\cdot \frac{l}{w}\) .(这个复杂度可能可以过 我也没试过。 黑科技 在线维护带修改线性基。 具体操作: 维护线性基的同时 再维护每线性基中每一个主元是由哪写向量异或而成的。 修改其中的一个向量x的时候 找到由它异或而成的行中1的位数最低的那个行向量w(有零行选零行. 找到之后将其他被x异或过的向量 再一一异或一遍 因为此时我们把w当作x 此时w要被修改所以凡是异或过x的都要修改。

栗酱的异或和

浪子不回头ぞ 提交于 2020-04-01 08:03:32
不进位加法 要写成 < ,不是 <= #include <bits/stdc++.h> using namespace std; #define int long long const int maxn = 1e5 + 5; int t,n,k; int a[maxn],ans; signed main(){ //freopen("in","r",stdin); ios::sync_with_stdio(0); cin >> t; while(t--){ cin >> n >> k; ans = 0; for(int i = 1; i <= n; i++){ cin >> a[i]; ans ^= a[i]; } if((ans ^ a[k]) < a[k]) cout << "Yes" << endl; else cout << "No" << endl; } return 0; } 来源: https://www.cnblogs.com/xcfxcf/p/12610133.html

不用加减乘除做加法

放肆的年华 提交于 2020-03-31 08:57:37
题目:写一个函数,求两个整数之和,要求在函数体内不得使用“+、-、*、/”四则运算符号 解题思路:对数字做运算除了四则运算之外,也就只剩下位运算了。位运算是针对二进制的,我们就以二进制再来分析一下前面的三步走策略对二进制是不是也适用。 5的二进制是101,17的二进制是10001.还是试着把计算分成三步:第一步歌薇相加但不计进位,得到的结果是10100(最后一位两个数都是1,相加的结果是二进制的10.这一步不计进位,因此结果仍然是0);第二步记下进位。在这个例子中只在最后一位相加时产生一个进位,结果是二进制的10;第三步把前两步的结果相加,得到的结果是10110,转换成十进制正好是22.由此可见三步走的策略对二进制也是适用的。 接下来我们试着把二进制的加法用位运算来替代。第一步不考虑进位对每一位相加。0加0,1加1的结果都是0,0加1,1加0的结果都是1.我们注意到,这和异或的结果是一样的。对异或而言,0和0、1和1异或的结果是0,而0和1、1和0异或的结果是1.接着考虑第二步进位,对0加0、0加1、1加0而言,都不会产生进位,只有1加1时,会向前产生一个进位。此时我们可以想象成是两个数先做位与运算,然后再向左移动一位。只有两个数都是1的时候,位与得到的结果是1,其余都是0.第三步把前两个步骤的结果相加。第三步相加的过程依然是重复前面两步,直到不产生进位为止。 来源: https:

Single Number leetcode java

五迷三道 提交于 2020-03-31 07:57:43
题目: Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 题解: 这道题运用位运算的异或。异或是相同为0,不同为1。所以对所有数进行异或,得出的那个数就是single number。初始时先让一个数与0异或,然后再对剩下读数挨个进行异或。 这里运用到异或的性质: 对于任何数x,都有x^x=0,x^0=x 代码如下: 1 public int singleNumber( int [] A) { 2 int result = 0; 3 for ( int i = 0; i<A.length;i++){ 4 result = result^A[i]; 5 } 6 return result; 7 } 同时异或还有性质: 交换律 A XOR B = B XOR A 结合律 A XOR B XOR C = A XOR (B XOR C) = (A XOR B) XOR C 自反性 A XOR B XOR B = A XOR 0 = A

[UOJ310][UNR #2]黎明前的巧克力

亡梦爱人 提交于 2020-03-29 19:04:12
题目    点这里 看题目。 分析   不难发现,设两人取得的下标集合为 \(S_a\) 和 \(S_b\) ,那么符合要求的下标集合对需要满足 \(S_a\) 和 \(S_b\) 对应的值全部异或起来为 0 。   因此,我们可以考虑异或为 \(0\) 的下标集合 \(S\) ,它对答案的贡献就是 \(2^{|S|}\) 。   根据这个思想,我们可以考虑如下的 DP :    \(f(i,j)\) :前 \(i\) 个数,异或为 \(j\) 的集合的个数。转移如下: \[f(i,j)=f(i-1,j)+2f(i-1,j\oplus a_i) \]   这样当然是没有办法做的。不过我们可以考虑将这样的转移写成生成函数的形式: \[A(i)=1+2x^{a_i}, F=\prod_{i=1}^n\sum_{j=0} f(i,j)x^j \] \[\Rightarrow F=\bigoplus_{j=1}^i A(j) \]   其中的 \(\bigoplus\) 运算符为异或卷积,可以理解为系数相乘,指数异或。   说着异或卷积,貌似就可以 FWT ?   显然不行,这样时间有 \(O(n^2\log_2n)\) ,会 T 的,我们需要继续挖掘性质。   我们想想 FWT 之后的序列的性质: \[FWT(a)_i=\sum_j (-1)^{count(i\&j)}a_j \]  

leetcode 136

喜欢而已 提交于 2020-03-24 11:55:43
136. Single Number Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 数组中只有一个数只出现一次,其余的数都出现两次,找出出现一次的那个数。采用异或运算来处理。 异或运算的性质:任何一个数字异或它自己都等于 0 。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现依次的数字,因为那些出现两次的数字全部在异或中抵消掉了。 代码如下: 1 class Solution { 2 public: 3 int singleNumber(vector<int>& nums) { 4 int n = 0; 5 for(int i = 0; i < nums.size(); i++) 6 { 7 n ^= nums[i]; 8 } 9 return n; 10 } 11 }; 来源: https://www.cnblogs.com/shellfishsplace/p/5932545

最大异或对

旧城冷巷雨未停 提交于 2020-03-24 03:44:03
# 题意 给定n个整数a 1 ,a 2 ,......a n ,从中选两个进行异或运算,求可以得到的最大值 N∈[1,1e5] A i ∈[0,2 31 ] # 题解 将每个整数看作32位的二进制01串(数值小在前面补0),把每一个数都插入trie树中, 高位在上,每一步都尝试找与当前不同的字符向下访问,显然高位上尽量为1时最优 节点个数最多有N*31 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int n,ans; 5 int trie[N*32][2],tot=1; 6 inline void insert(int x){ 7 int p=1; 8 for(int i=30;i>=0;i--){ 9 int u=(x>>i)&1; 10 if(!trie[p][u]) trie[p][u]=++tot; 11 p=trie[p][u]; 12 } 13 } 14 inline int search(int x){ 15 int p=1,res=0; 16 for(int i=30;i>=0;i--){ 17 int u=(x>>i)&1; 18 if(trie[p][!u]){ 19 p=trie[p][!u]; 20 res+=(1<<i); 21 } 22 else 23

最长异或路径值

本秂侑毒 提交于 2020-03-24 03:42:54
# 题意 给定一个n个节点的树,树上的边都具有权值,从树中任意选两个点,求两点上的路径值异或起来的最大值 # 题解 数组D[x]表示根节点到x的路径上所有的边权的xor值,并且结构是树,通过dfs求出所有节点的d 求出所有的D数组,那么x节点到y节点上所有的异或权值就是D[x] xor D[y],如果从根分叉的话没有疑问 如果一个节点是另一个节点的祖先节点节点,根据异或性质就可以把从根到祖先节点公共路径抵消 原问题就转换成为D[1]~D[n]中选择任意两个数,求最大的异或值. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int n; 5 int h[N],e[N*2],ne[N*2],w[N*2],idx; 6 int d[N]; 7 int trie[N*31][2],tot=1; 8 inline void add(int x,int y,int z){ 9 e[idx]=y; 10 w[idx]=z; 11 ne[idx]=h[x]; 12 h[x]=idx++; 13 } 14 inline int dfs(int u,int f,int sum){ 15 d[u]=sum; 16 for(int i=h[u];i!=-1;i=ne[i]){ 17 int j=e[i];