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 }
在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 }
若子集异或为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 }
求第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 }
即求出线性基,然后贪心取即可。
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 }
倍增合并线性基,贪心求最大值即可