【算法总结】线性代数相关
【线性基】
〖相关资料〗
〖注意事项〗
左移时记得1ll。
〖模板代码〗
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #define LL long long 6 using namespace std; 7 const int N=55; 8 LL n,ans,x[N],a[N]; 9 LL read() 10 { 11 LL x=0,f=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 13 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 14 return x*f; 15 } 16 int main() 17 { 18 n=read(); 19 for(int i=1;i<=n;i++)x[i]=read(); 20 for(int i=1;i<=n;i++) 21 for(int j=50;j>=0;j--) 22 { 23 if(!(x[i]&(1ll<<j)))continue; 24 if(!a[j]){a[j]=x[i];break;} 25 x[i]^=a[j]; 26 } 27 for(int i=50;i>=0;i--) 28 if((ans^a[i])>ans)ans=ans^a[i]; 29 printf("%lld",ans); 30 return 0; 31 }
〖相关题目〗
1.【bzoj2460】[BeiJing2011]元素
题意:见原题
分析:hzwerの博客
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 using namespace std; 6 const int N=1e3+5; 7 LL n,ans,bin[65],b[65]; 8 struct node{LL id;int w;}a[N]; 9 LL read() 10 { 11 LL x=0,f=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 13 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 14 return x*f; 15 } 16 bool cmp(node a,node b){return a.w>b.w;} 17 int main() 18 { 19 n=read(); 20 for(int i=1;i<=n;i++)a[i].id=read(),a[i].w=read(); 21 sort(a+1,a+n+1,cmp); 22 for(int i=1;i<=n;i++) 23 { 24 for(int j=63;j>=0;j--) 25 if(a[i].id&(1ll<<j)) 26 { 27 if(!b[j]){b[j]=a[i].id;break;} 28 a[i].id^=b[j]; 29 } 30 if(a[i].id)ans+=a[i].w; 31 } 32 printf("%lld",ans); 33 return 0; 34 }
2.【bzoj2115】[Wc2011] Xor
题意:给定一个边权非负的无向连通图,求从1到n的最大xor和路径,存在重边,允许经过重复点、重复边。
分析:ljh_2000の博客
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #define LL long long 6 using namespace std; 7 const int N=5e4+5; 8 const int M=2e5+5; 9 int n,m,cnt,tot,x,y,first[N]; 10 LL ans,w,a[65],sum[N],cir[M]; 11 bool vis[N]; 12 struct edge{int to,next;LL w;}e[M]; 13 LL read() 14 { 15 LL x=0,f=1;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 18 return x*f; 19 } 20 void ins(int u,int v,LL w){e[++cnt]=(edge){v,first[u],w};first[u]=cnt;} 21 void dfs(int x) 22 { 23 vis[x]=true; 24 for(int i=first[x];i;i=e[i].next) 25 { 26 int to=e[i].to; 27 if(!vis[to])sum[to]=sum[x]^e[i].w,dfs(to); 28 else cir[++tot]=sum[x]^e[i].w^sum[to]; 29 } 30 } 31 int main() 32 { 33 n=read();m=read(); 34 for(int i=1;i<=m;i++) 35 { 36 x=read();y=read();w=read(); 37 ins(x,y,w);ins(y,x,w); 38 } 39 dfs(1);ans=sum[n]; 40 for(int i=1;i<=tot;i++) 41 for(int j=60;j>=0;j--) 42 { 43 if(!(cir[i]&(1ll<<j)))continue; 44 if(!a[j]){a[j]=cir[i];break;} 45 cir[i]^=a[j]; 46 } 47 for(int i=60;i>=0;i--)ans=max(ans,ans^a[i]); 48 printf("%lld\n",ans); 49 return 0; 50 }
3.【codeforces724G】Xor-matic Number of the Graph
题意:给定一个边权非负的无向图,定义三元组 (u, v, s) 为有趣的,当且仅当u、v(1 ≤ u < v ≤ n)间存在一条路径异或和为s,允许经过重复点、重复边。求所有有趣的三元组的s之和。
分析:ljh_2000の博客
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 using namespace std; 6 const int N=1e5+5; 7 const int M=4e5+5; 8 const int mod=1e9+7; 9 int n,m,x,y,CNT,tot,r,tail,q[N],first[N]; 10 LL w,ans,cnt[2],sum[N],two[65],a[65],cir[M]; 11 bool flag,vis[N]; 12 struct edge{int to,next;LL w;}e[M]; 13 LL read() 14 { 15 LL x=0,f=1;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 18 return x*f; 19 } 20 void ins(int u,int v,LL w){e[++CNT]=(edge){v,first[u],w};first[u]=CNT;} 21 void dfs(int x,int fa) 22 { 23 vis[x]=true;q[++tail]=x; 24 for(int i=first[x];i;i=e[i].next) 25 { 26 int to=e[i].to; 27 if(to==fa)continue; 28 if(!vis[to])sum[to]=sum[x]^e[i].w,dfs(to,x); 29 else cir[++tot]=sum[x]^e[i].w^sum[to]; 30 } 31 } 32 void build() 33 { 34 r=0;memset(a,0,sizeof(a)); 35 for(int i=1;i<=tot;i++) 36 for(int j=60;j>=0;j--) 37 { 38 if(!(cir[i]&(1ll<<j)))continue; 39 if(!a[j]){a[j]=cir[i];break;} 40 cir[i]^=a[j]; 41 } 42 for(int i=0;i<=60;i++)if(a[i])r++; 43 } 44 LL calc() 45 { 46 build();LL ans=0,now; 47 for(int i=0;i<=60;i++) 48 { 49 cnt[0]=cnt[1]=0;flag=false; 50 for(int j=0;j<=60;j++) 51 if(a[j]&(1ll<<i)){flag=true;break;} 52 for(int j=1;j<=tail;j++) 53 cnt[(sum[q[j]]>>i)&1]++; 54 now=(cnt[0]*(cnt[0]-1)/2+cnt[1]*(cnt[1]-1)/2)%mod; 55 if(flag)ans=(ans+now*two[r-1]%mod*two[i]%mod)%mod; 56 now=cnt[0]*cnt[1]%mod; 57 if(!flag)ans=(ans+now*two[r]%mod*two[i]%mod)%mod; 58 else ans=(ans+now*two[r-1]%mod*two[i]%mod)%mod; 59 } 60 return ans; 61 } 62 int main() 63 { 64 n=read();m=read(); 65 for(int i=1;i<=m;i++) 66 { 67 x=read();y=read();w=read(); 68 ins(x,y,w);ins(y,x,w); 69 } 70 two[0]=1; 71 for(int i=1;i<=61;i++)two[i]=two[i-1]*2%mod; 72 for(int i=1;i<=n;i++) 73 { 74 if(vis[i])continue; 75 tot=0;tail=0;dfs(i,-1); 76 ans=(ans+calc())%mod; 77 } 78 printf("%lld",ans); 79 return 0; 80 }