关于高斯消元解决xor问题的总结

我觉得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.
View Code

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.
View Code
原文地址:https://www.cnblogs.com/phile/p/4490111.html