[学习笔记]线性基
学长讲的,之前也在线性代数上看到过
zero4338大佬指正,这两个基本可以看做等价的
所以我自然结合了线性代数来乱搞(
约定用
1. 什么是线性基?
2. 线性基的性质
3. 构建一个线性基
#define int long long void insrt(int x){ for(int i=63;i>=0;i--){ if((x>>i)&1){ if(!base[i]){ base[i]=x; return; }else{ x^=base[i]; } } } }
4. 线性基的运算
0.判断一个数能否用线性基表示
1. 查询异或最大值

#include<cstdio> #include<cstring> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=1010; int n,ans; int base[WR],a[WR]; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } void insrt(int x){ for(int i=63;i>=0;i--){ if((x>>i)&1){ if(!base[i]){ base[i]=x; return; }else{ x^=base[i]; } } } } signed main(){ n=read(); for(int i=1;i<=n;i++){ a[i]=read(); insrt(a[i]); } for(int i=63;i>=0;i--){ if((ans^base[i])>ans) ans^=base[i]; } printf("%lld\n",ans); return 0; }
2.查询异或最小值

#include<cstdio> #include<cstring> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=1010; int n,ans; int base[WR],a[WR]; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } void insrt(int x){ for(int i=63;i>=0;i--){ if((x>>i)&1){ if(!base[i]){ base[i]=x; return; }else{ x^=base[i]; } } } } signed main(){ n=read(); for(int i=1;i<=n;i++){ a[i]=read(); insrt(a[i]); if(a[i]==0){ printf("0\n"); return 0; } } for(int i=0;i<=63;i++){ if(base[i]){ printf("%lld\n",base[i]); return 0; } } return 0; }
3. 查询异或排名

#include<cstdio> #include<cstring> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=100100,mod=10086; int n,ans,q; int stk[WR],cnt; int rnk; int base[WR],val[WR]; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } int quick_pow(int a,int b){ int bse=a,res=1; while(b){ if(b&1) res=res*bse%mod; bse=bse*bse%mod; b>>=1; } return res; } void insrt(int x){ for(int i=31;i>=0;i--){ if((x>>i)&1){ if(!base[i]){ base[i]=x; return; }else{ x^=base[i]; } } } } signed main(){ n=read(); for(int i=1;i<=n;i++){ int x=read(); insrt(x); } q=read(); for(int i=0;i<=31;i++){ if(base[i]) stk[++cnt]=i; } for(int i=1;i<=cnt;i++){ //printf("%lld ",stk[i]); if((q>>stk[i])&1) rnk=(rnk+quick_pow(2,i))%mod; } printf("%lld\n",(rnk*quick_pow(2,n-cnt-1)%mod+1)%mod); return 0; }
4. 线性基的合并

#include<cstdio> #include<cstring> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=50100; struct Edge{ int pre,to; }edge[WR<<1]; int n,q; int head[WR],tot; int dpt[WR],fa[WR][20]; int base[WR][20][65]; int ans[WR]; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } void get_base(int a[],int val){ for(int i=63;i>=0;i--){ if((val>>i)&1){ if(!a[i]){ a[i]=val; return; }else{ val^=a[i]; } } } } void merge_base(int a[],int b[]){ for(int i=0;i<=63;i++) if(b[i]) get_base(a,b[i]); } void add(int u,int v){ edge[++tot].pre=head[u]; edge[tot].to=v; head[u]=tot; } void dfs(int u,int root){ fa[u][0]=root; dpt[u]=dpt[root]+1; for(int i=1;i<=19;i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; memcpy(base[u][i],base[u][i-1],sizeof(base[u][i-1])); merge_base(base[u][i],base[fa[u][i-1]][i-1]); } for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to; if(v==root) continue; dfs(v,u); } } void LCA(int x,int y){ if(dpt[x]<dpt[y]) swap(x,y); for(int i=19;i>=0;i--){ if(dpt[fa[x][i]]>=dpt[y]){ merge_base(ans,base[x][i]); x=fa[x][i]; } } if(x==y){ merge_base(ans,base[x][0]); return; } for(int i=19;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ merge_base(ans,base[x][i]); merge_base(ans,base[y][i]); x=fa[x][i],y=fa[y][i]; } } merge_base(ans,base[x][0]); merge_base(ans,base[y][0]); merge_base(ans,base[fa[x][0]][0]); //printf("%lld and %lld's LCA = %lld\n",x,y,fa[x][0]); } signed main(){ n=read(),q=read(); for(int i=1;i<=n;i++){ int t=read(); get_base(base[i][0],t); } for(int i=1;i<n;i++){ int u=read(),v=read(); add(u,v);add(v,u); } dfs(1,0); while(q--){ int x=read(),y=read(); memset(ans,0,sizeof(ans)); LCA(x,y); int res=0; for(int i=63;i>=0;i--){ if((res^ans[i])>res) res^=ans[i]; } printf("%lld\n",res); } return 0; }
本文来自博客园,作者:冬天的雨WR,转载请注明原文链接:https://www.cnblogs.com/WintersRain/p/16517012.html
为了一切不改变的理想,为了改变不理想的一切
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现