Xor && 线性基练习

 1 #include <cstdio>
 2 #include <cstring>
 3 const int Len=31;
 4 const int Maxn=100100;
 5 int cnt,Ans,b,x,n;
 6 inline int Max(int x,int y) {return x>y?x:y;}
 7 struct Node {int next[2];}Tree[Maxn*Len];
 8 void Insert(int x)
 9 {
10     int Now=0; bool k;
11     for (int i=Len;i>=0;i--)
12     {
13         k=x&(1<<i);
14         if (Tree[Now].next[k]==-1) Tree[Now].next[k]=++cnt;
15         Now=Tree[Now].next[k];
16     }
17 }
18 int Query(int x)
19 {
20     int Now=0,v=0; bool k;
21     for (int i=Len;i>=0;i--)
22     {
23         k=x&(1<<i);
24         if (Tree[Now].next[!k]!=-1) k=!k;
25         v=v|(k<<i);
26         Now=Tree[Now].next[k];
27     }
28     return v;
29 }
30 int main()
31 {
32     // freopen("c.in","r",stdin);
33     while (scanf("%d",&n)!=EOF)
34     {
35         Ans=cnt=0; memset(Tree,-1,sizeof(Tree));
36         for (int i=1;i<=n;i++)
37         {
38             scanf("%d",&x);
39             Insert(x);
40             Ans=Max(Ans,x^Query(x));
41         }
42         printf("%d
",Ans);
43     }
44     return 0;
45 }
CSU1216

在n个数取两个Xor最大。用0-1Trie.

 1 #include <cstdio>
 2 #include <algorithm>
 3 #define LL long long
 4 using namespace std;
 5 LL n,Ans,Base[1010];
 6 struct Node{LL a,b;}A[1010];
 7 inline bool cmp(Node A,Node B) {return A.b>B.b;}
 8  
 9 int main()
10 {
11     scanf("%lld",&n);
12     for (LL i=1;i<=n;i++) scanf("%lld%lld",&A[i].a,&A[i].b);
13     sort(A+1,A+n+1,cmp); Ans=0;
14     for (LL i=1;i<=n;i++)
15     {
16         for (LL j=63;j>=0;j--)
17             if (A[i].a>>j&1)
18             {
19                 if (!Base[j])
20                 {
21                     Base[j]=A[i].a;
22                     break;
23                 }
24                 A[i].a^=Base[j];
25             }
26         if (A[i].a) Ans+=A[i].b;
27     }
28     printf("%lld
",Ans);
29     return 0;
30 }
BZOJ2460

若子集异或为0,则集合一定不为线性基。从大到小排序,贪心即可。

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 #define LL long long
 5 const LL Maxn=100100;
 6 LL a[Maxn],Kase,n,Ans,k,q,Bin[100];
 7 inline void Swap(LL &x,LL &y) {LL t=x;x=y;y=t;}
 8 inline LL Get(LL Row,LL k)
 9 {
10     if (Row<n)
11     {if (k==1) return 0; else k--;}
12     if (k>=Bin[Row]) return -1;
13     LL Ret=0;
14     for (int i=1;i<=Row;i++)
15         if (k&Bin[Row-i]) Ret^=a[i];
16     return Ret;
17 }
18 int main()
19 {
20     scanf("%I64d",&Kase);
21     Bin[0]=1; for (int i=1;i<=60;i++) Bin[i]=Bin[i-1]<<1;
22     for (LL kase=1;kase<=Kase;kase++)
23     {
24         printf("Case #%I64d:
",kase);
25         scanf("%I64d",&n);
26         for (LL i=1;i<=n;i++) scanf("%I64d",&a[i]);
27         LL Now=0;
28         for (LL i=Bin[60];i;i>>=1)
29         {
30             LL j=Now+1;
31             while (!(i&a[j])&&j<=n) j++;
32             if (j==n+1) continue;
33             ++Now; Swap(a[Now],a[j]);
34             for (j=1;j<=n;j++)
35             {
36                 if (j==Now) continue;
37                 if (a[j]&i) a[j]=a[j]^a[Now];
38             }
39         }        
40         scanf("%I64d",&q);
41         for (LL i=1;i<=q;i++)
42         {
43             scanf("%I64d",&k);
44             printf("%I64d
",Get(Now,k));
45         }
46     }
47     return 0;
48 }
HDU3949

求第K大的Xor和,求出线性基,把K转为二进制在Xor就可以了

 1 #include <cstdio>
 2 #include <algorithm>
 3 #define LL long long
 4 using namespace std;
 5 const LL Mod=1000000009;
 6 const LL Maxn=1010;
 7 struct Node{LL b[Maxn],c;}a[Maxn];
 8 LL Base[Maxn],cnt,Ans,n,m;
 9 inline LL Pow(LL x,LL y)
10 {
11     LL Ret=1;
12     while (true)
13     {
14         if (y&1) Ret=(Ret*x)%Mod;
15         x=(x*x)%Mod; y>>=1; 
16         if (y==0) break;
17     }
18     return Ret;
19 }
20 inline bool cmp(Node A,Node B) {return A.c<B.c;}
21 int main()
22 {
23     scanf("%lld%lld",&n,&m);
24     for (LL i=1;i<=n;i++)
25         for (LL j=1;j<=m;j++) scanf("%lld",&a[i].b[j]);
26     for (LL i=1;i<=n;i++) scanf("%lld",&a[i].c);
27     sort(a+1,a+n+1,cmp);
28     for (LL i=1;i<=n;i++)
29     {
30         bool flag=false;
31         for (LL j=1;j<=m;j++)
32             if (a[i].b[j])
33             {
34                 if (!Base[j])
35                 {
36                     Base[j]=i; flag=true;
37                     break;
38                 }
39                 LL t=Mod-(a[i].b[j]*Pow(a[Base[j]].b[j],Mod-2))%Mod;
40                 for (LL k=j;k<=m;k++)
41                     a[i].b[k]=(a[i].b[k]+(t*a[Base[j]].b[k])%Mod)%Mod;
42             }
43         if (flag) Ans+=a[i].c,cnt++;
44     }
45     printf("%lld %lld
",cnt,Ans);
46     return 0;
47 }
BZOJ4004

即求出线性基,然后贪心取即可。

  1 #include <cstdio>
  2 #include <cstring>
  3 #define LL long long
  4 inline void Get_Int(LL & x)
  5 {
  6     char ch=getchar(); x=0;
  7     while (ch<'0' || ch>'9') ch=getchar();
  8     while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
  9 }
 10 inline void Swap(LL &x,LL &y) {LL t=x;x=y;y=t;}
 11 inline LL Max(LL x,LL y) {return x>y?x:y;}
 12 inline LL Min(LL x,LL y) {return x>y?y:x;}
 13 //==================================================
 14 const LL Maxn=20010;
 15 LL head[Maxn],father[Maxn][20],Dep[Maxn],n,m,Bin[70],x,u,v,cnt,Sum;
 16 bool vis[Maxn];
 17 struct Edge{LL to,next;}edge[Maxn<<2];
 18 struct Base
 19 {
 20     LL a[70];
 21     inline void Clr() {memset(a,0,sizeof(a));}
 22     inline void Insert(LL x) 
 23     {
 24         for (LL i=60;i>=0;i--)
 25             if (Bin[i]&x) 
 26             {
 27                 if (!a[i]) {a[i]=x; return;}
 28                 x^=a[i];
 29             }
 30     }
 31 }; 
 32 Base f[Maxn][20],Ans;
 33 inline void Add(LL u,LL v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
 34 void Dfs(LL u)
 35 {
 36     vis[u]=true;
 37     for (LL i=head[u];i!=-1;i=edge[i].next) 
 38         if (!vis[edge[i].to])
 39         {
 40             father[edge[i].to][0]=u;
 41             Dep[edge[i].to]=Dep[u]+1;
 42             Dfs(edge[i].to);
 43         }
 44 }
 45 inline void Init()
 46 {
 47     for (LL j=1;j<=15;j++)
 48         for (LL i=1;i<=n;i++)
 49         {
 50             father[i][j]=father[father[i][j-1]][j-1];
 51             for (LL k=60;k>=0;k--) if (f[i][j-1].a[k])f[i][j].Insert(f[i][j-1].a[k]);
 52             for (LL k=60;k>=0;k--) if (f[father[i][j-1]][j-1].a[k])f[i][j].Insert(f[father[i][j-1]][j-1].a[k]);
 53         }
 54 }
 55 void Solve(LL u,LL v)
 56 {
 57     if (Dep[u]<Dep[v]) Swap(u,v);
 58     for (LL i=15;i>=0;i--)
 59         if (Dep[father[u][i]]>=Dep[v])
 60         {
 61             for (LL k=60;k>=0;k--) if (f[u][i].a[k]) Ans.Insert(f[u][i].a[k]);
 62             u=father[u][i];
 63         }
 64     if (u==v) 
 65     {
 66         for (LL k=60;k>=0;k--) if (f[u][0].a[k]) Ans.Insert(f[u][0].a[k]);
 67         return;
 68     }
 69      
 70     for (LL i=15;i>=0;i--)
 71         if (father[u][i]!=father[v][i])
 72         {
 73             for (LL k=60;k>=0;k--) if (f[u][i].a[k]) Ans.Insert(f[u][i].a[k]);
 74             for (LL k=60;k>=0;k--) if (f[v][i].a[k]) Ans.Insert(f[v][i].a[k]);
 75             u=father[u][i],v=father[v][i];
 76         }
 77     for (LL k=60;k>=0;k--) if (f[u][0].a[k])Ans.Insert(f[u][0].a[k]);
 78     for (LL k=60;k>=0;k--) if (f[v][0].a[k])Ans.Insert(f[v][0].a[k]);
 79     for (LL k=60;k>=0;k--) if (f[father[u][0]][0].a[k])Ans.Insert(f[father[u][0]][0].a[k]);
 80 }
 81  
 82 int main()
 83 {
 84     Bin[0]=1; for (LL i=1;i<=60;i++) Bin[i]=Bin[i-1]<<1;
 85     Get_Int(n),Get_Int(m);
 86     for (LL i=1;i<=n;i++)
 87     {
 88         Get_Int(x);
 89         f[i][0].Insert(x);
 90     }
 91     memset(head,-1,sizeof(head));
 92     for (LL i=1;i<n;i++)
 93     {
 94         Get_Int(u),Get_Int(v);
 95         Add(u,v),Add(v,u);
 96     }
 97     father[1][0]=1; Dep[1]=1;
 98     memset(vis,false,sizeof(vis)); Dfs(1);
 99     Init();
100     for (LL i=1;i<=m;i++)
101     {
102         Get_Int(u),Get_Int(v);
103         Ans.Clr();
104         Solve(u,v); Sum=0;
105         for (LL j=60;j>=0;j--) Sum=Max(Sum,Sum^Ans.a[j]);
106         printf("%lld
",Sum);
107     }
108     return 0;
109 }
BZOJ4568

倍增合并线性基,贪心求最大值即可

原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5676589.html