我觉得xor这东西特别神奇,最神奇的就是这个性质了 A xor B xor B=A
这样就根本不用在意重复之类的问题了
关于xor的问题大家可以去膜拜莫队的《高斯消元解XOR方程组》,里面写的很详细
我来扯两道bzoj上的例题好了
bzoj2115,求1-N最长xor路径,根据那个神奇的性质,我们先随便找一条1-n的路径作为标准路径
任意一条1-N的路径都等价于标准路径和某些环的xor
怎么找环?很简单,bfs下去,设d[x]表示1到x的一条路径xor值,如果到一条边x-->y时y已经访问过了,那么d[x] xor d[y] xor w[x,y]就是一个环
然后这个问题就转变成了求一堆数中任意数xor最大的问题,这我们是通过求线性基然后按位贪心就可以了
1 type node=record 2 po,next:longint; 3 num:int64; 4 end; 5 6 var f:array[0..64] of int64; 7 d:array[0..50010] of int64; 8 q,p:array[0..50010] of int64; 9 a:array[0..500010] of int64; 10 e:array[0..200010] of node; 11 x,y,i,n,m,len,t:longint; 12 ans,z:int64; 13 14 procedure add(x,y:longint;z:int64); 15 begin 16 inc(len); 17 e[len].po:=y; 18 e[len].num:=z; 19 e[len].next:=p[x]; 20 p[x]:=len; 21 end; 22 23 procedure bfs; 24 var h,r,i,x,y:longint; 25 begin 26 fillchar(d,sizeof(d),255); 27 d[1]:=0; 28 h:=1; r:=1; q[1]:=1; 29 while h<=r do 30 begin 31 x:=q[h]; 32 i:=p[x]; 33 while i<>0 do 34 begin 35 y:=e[i].po; 36 if d[y]=-1 then 37 begin 38 d[y]:=d[x] xor e[i].num; 39 inc(r); 40 q[r]:=y; 41 end 42 else if d[y] xor d[x] xor e[i].num<>0 then //找环 43 begin 44 inc(t); 45 a[t]:=d[y] xor d[x] xor e[i].num; 46 end; 47 i:=e[i].next; 48 end; 49 inc(h); 50 end; 51 end; 52 53 procedure gauss; 54 var i,j:longint; 55 begin 56 for i:=1 to t do 57 for j:=60 downto 0 do 58 if a[i] and (int64(1) shl j)>0 then //求线性基 59 begin 60 if f[j]=0 then 61 begin 62 f[j]:=a[i]; 63 break; 64 end 65 else a[i]:=a[i] xor f[j]; 66 end; 67 68 ans:=d[n]; 69 for i:=60 downto 0 do 70 if ans and (int64(1) shl i)=0 then ans:=ans xor f[i]; 71 end; 72 73 begin 74 readln(n,m); 75 for i:=1 to m do 76 begin 77 readln(x,y,z); 78 add(x,y,z); 79 add(y,x,z); 80 end; 81 bfs; 82 gauss; 83 writeln(ans); 84 end.
bzoj2844
一堆数xor能产生数的种类数就是2^线性基的秩
并且每个数出现的次数是一样的(求证明)
然后我们就可以做了,注意这里的线性基要用高斯消元求而不能用上题的方法
因为要计算某个数出现在第几位,必须使线性基相互xor的数的大小满足二进制位的大小关系
举个例子,比如线性基a,b,c并且a>b>c,如果取a,b xor,选取状况为110,这样选取xor的数一定要比011这样选大,我们称之为满足二进制大小关系(我自己口胡的名词)
1 const mo=10086; 2 3 var a,d:array[0..100010] of longint; 4 f,b:array[0..40] of longint; 5 k,p,i,j,n,ans,m,t:longint; 6 7 procedure swap(var a,b:longint); 8 var c:longint; 9 begin 10 c:=a; 11 a:=b; 12 b:=c; 13 end; 14 15 begin 16 readln(n); 17 for i:=1 to n do 18 read(a[i]); 19 d[0]:=1; 20 for i:=1 to n do 21 d[i]:=d[i-1]*2 mod mo; 22 23 readln(m); 24 k:=n; 25 for i:=1 to n do 26 begin 27 for j:=i+1 to n do 28 if a[i]<a[j] then swap(a[i],a[j]); 29 if a[i]=0 then 30 begin 31 k:=i-1; 32 break; 33 end; 34 for j:=30 downto 0 do 35 if a[i] and (1 shl j)>0 then 36 begin 37 b[i]:=j; 38 for p:=1 to n do 39 if (p<>i) and (a[p] and (1 shl j)>0) then 40 a[p]:=a[p] xor a[i]; 41 break; 42 end; 43 end; 44 ans:=1; 45 for i:=1 to k do 46 if m and (1 shl b[i])>0 then 47 begin 48 m:=m xor a[i]; 49 ans:=(ans+d[k-i+n-k]) mod mo; 50 end; 51 52 writeln(ans); 53 end.