首页 > 其他分享 >线性基笔记

线性基笔记

时间:2024-10-16 15:32:13浏览次数:6  
标签:int res 笔记 异或 线性 inline define

线性基是一种在异或操作上有很大用处的数据结构。

可以求异或最值,区间异或最值的问题

可以用来水各种题

线性基的定义

1.线性基能相互异或得到原集合的所有相互异或得到的值。
2.线性基是满足性质1的最小的集合
3.线性基没有异或和为0的子集。

线性基的插入

二进制下拆分数x,从高位向低位扫
若x再当前位为1,就判断当前位线性基是否有值,
若有就把x的当前位消掉,否则就加入线性基

线性基的插入函数如下:

inline bool Insert(int x) {
	drep(i,60,0)if(x&(1ll<<i)) {
		if(d[i])x^=d[i];
		else {
			d[i]=x;
			break;
		}
	}
	return x>0;
}

查询异或最值

查询最小值相对比较简单。线性基中最小值异或上其他数,必定增大。所以,直接输出线性基中的最小值即可。

考虑异或最大值,从高到低遍历线性基,考虑到第&i&位时,如果当前的答案第&i&位为0,就将其异或上 ;
否则不做任何操作。显然,每次操作后答案不会变劣,最终的结果即为答案。

inline int Query_max () {
	int res=0;
	drep(i,63,0)Max(res,res^d[i]);
	return res;
}

inline int Query_min () {
	rep(i,0,63)if(d[i])return d[i];
}

查询异或第&k&小值

1.照例建立线性基
2.使得线性基中有且只有base[i]的第i位为1
3.记录所有有值的base[] 从低位到高位记为0~cnt,共cnt + 1个 (注:闭区间
这时线性基可以构成的数有(1 << cnt) + 1个,如果cnt + 1 < n的话 说明可以取零 这时可以构成的数有(1 << (cnt + 1))个
4.取第k小时,如果k大于可以构成的数的总数 那么无解
否则res是所有base[i] ((k - 1)的第i位为1) 的异或和


using namespace std;

#define int long long
#define u64 unsigned long long
#define u32 unsigned int
#define reg register
#define Raed Read
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(reg int i=(G).Head[x]; i; i=(G).Nxt[i])

inline int Read() {
	int res  = 0, f = 1;
	char c;
	while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
	do res = (res << 3) + (res << 1) + (c ^ 48);
	while (c = getchar(), c >= 48 && c <= 57);
	return f ? res : -res;
}

template<class T>inline bool Min(T &a, T const&b) {
	return a > b ? a = b, 1 : 0;
}
template<class T>inline bool Max(T &a, T const&b) {
	return a < b ? a = b, 1 : 0;
}

const int N=1e3+5,M=1e5+5,mod=1e9+7;

bool MOP1;

int n,d[65],A[65],cnt;

bool MOP2;

inline bool Insert(int x) {
	drep(i,60,0)if(x&(1ll<<i)) {
		if(d[i])x^=d[i];
		else {
			d[i]=x;
			break;
		}
	}
	return x>0;
}

inline void build(void) {
	drep(i,60,0) {
		if(!d[i])continue;
		drep(j,i-1,0) {
			if(!d[j])continue;
			if(d[i]&(1ll<<j))d[i]^=d[j];
		}
	}
	rep(i,0,60)if(d[i])A[cnt++]=d[i];
}

inline int Find(int x) {
	if(cnt<n)x--;
//	debug(cnt);
	if(x>=(1ll<<cnt))return -1;
	int Ans=0;
	ret(i,0,cnt)if(x&(1ll<<i))Ans^=A[i];
	return Ans;
}

inline void _main(void) {
//  cerr<<"M="<<(&MOP2-&MOP1)/1024.0/1024.0<<endl;
	int T=Read(),Case=0;
	while(T--) {
		memset(d,0,sizeof d);
		cnt=0,n=Read();
		rep(i,1,n)Insert(Read());
		build();
		int m=Raed();
		printf("Case #%d:\n",++Case);
		rep(i,1,m)printf("%lld\n",Find(Raed()));
	}
}

signed main() {
	_main();
}

线性基求区间异或最值

与序列的同理,加上编号记录一波即可,若右端点最值编号在左端点右边即可更新


using namespace std;

#define int long long
#define reg register
#define rep(a,b,c) for(reg int a=(b),a##_end_(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_(c); a>=a##_end_; --a)

inline void Rd(int &res) {
    res=0;
    int flag=0;
    char c;
    while(c=getchar(),c<48||c>57)flag|=(c=='-');
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>=48&&c<=57);
    flag&&(res=-res);
}

template<class T>inline bool Max(T &a,T b) {return a<b?a=b,1:0;}
template<class T>inline bool Min(T &a,T b) {return a>b?a=b,1:0;}

const int N=5e5+5,INF=0x3f3f3f3f,mod=998244353;

int n,m,P[25][N],Id[25][N];

inline void Insert(int x,int y){
	int pre=y;
	rep(i,0,20)P[i][y]=P[i][y-1],Id[i][y]=Id[i][y-1];
	drep(i,20,0)if(x>>i&1){
		if(!P[i][y]){
			P[i][y]=x,Id[i][y]=pre;
			return;
		}
		if(Id[i][y]<pre)swap(Id[i][y],pre),swap(P[i][y],x);
		x^=P[i][y];
	}
	return;
}

inline int query(int L,int R){
	int Ans=0;
	drep(i,20,0)if((Ans^P[i][R])>Ans&&(Id[i][R]>=L))Ans^=P[i][R];
	return Ans;
}

inline void solve(){
	Rd(n);
	int x;
	rep(i,1,n)Rd(x),Insert(x,i);
	Rd(m);
	while(m--){
		int L,R;
		Rd(L),Rd(R);
		printf("%lld\n",query(L,R));
	}
}

signed main(){
	solve(); 
}

标签:int,res,笔记,异或,线性,inline,define
From: https://www.cnblogs.com/dsjkafdsaf/p/18470097

相关文章

  • 关于Gmap.Net在WPF中的运用笔记(一)初步加载高德地图
    一、前言最近公司需要开发一个车辆在途轨迹追踪的软件,结合现有系统和技术体系,最终敲定使用WPF+Gmap.Net来实现,这里将一些坑踩一下,做个笔记记录一下。二、项目搭建本项目基于.Net6.0+Gmap.Net.Core+Gmap.Net.WinPresentation,前面是用到的框架版本,后面则是需要用到的地图包,可通......
  • FFmpeg开发笔记(五十七)使用Media3的Transformer加工视频文件
    ​继音视频播放器ExoPlayer之后,谷歌又推出了音视频转换器Transformer,要在音视频加工领域施展拳脚。根据Android开发者官网介绍:JetpackMedia3是Android媒体库的新家,可让App呈现丰富的视听体验。Media3提供了一个简单的架构,能够基于设备功能开展自定义与可靠性优化,可以解决媒体部分......
  • 读书笔记《稀缺-我们是如何陷入贫穷与忙碌的》2023-6-21
    读书笔记《稀缺-我们是如何陷入贫穷与忙碌的》2023-6-21基本信息书名:《稀缺-我们是如何陷入贫穷与忙碌的》作者:[美]塞德希尔·穆来纳森(SendhilMullainathan)[美]埃尔德·莎菲尔(EldarShafir)​​​​译者:魏薇龙志勇出版社:浙江教育出版社.湛庐出版时间:2022年10月......
  • Caffeine学习笔记
    作者:京东工业孙磊一、认识Caffeine1、Caffeine是什么?Caffeine是一个基于Java8开发的提供了近乎最佳命中率的高性能的缓存库,也是SpringBoot内置的本地缓存实现。2、Caffeine提供了灵活的构造器去创建一个拥有下列特性的缓存:•自动加载条目到缓存中,可选异步方式•可以基于大小剔除......
  • 读书笔记《PPT演讲力》大树模型
    作者把PPT演讲比作一棵大树,树的每一部分对应着PPT演讲的一个技巧。根据这个大树模型,是否有联想到自己过往的演讲经历?演讲是否都达到了大树模型中说的效果?根据这个思维导图,结合自己的经历,试着总结3句关于自己的演讲经历的话,可以是演讲成功总结、演讲没达到的效果的总结、演......
  • spring上 -基于注解配置bean,动态代理,AOP笔记
     用的是jdk8,spring框架里jar包的下载可以自己搜到注解用到的jar包。  60,注解配置Bean快速入门 基本介绍 代码结构: UserDao.javapackagecom.hspedu.spring.component;importorg.springframework.stereotype.Repository;/**使用@Repository标识该......
  • bootloader学习笔记-从零开发bootloader(4)
    概要Flash区域划分,从不同的区域启动用户程序,实现覆写代码的功能。Flash区域划分我们的Flash是从0x08000000开始的,具体能用的大小需要查看芯片手册,例如,我的GD32F303RC芯片,flash可用的区域为256KB,内存可用大小为48KB。256KB也就是262144字节的大小,转换成16进制为0x40000,也......
  • CF1672F 做题笔记
    CF1672F1CF1672F2考虑给定\(b\)算它的最小操作次数,我们将\(a_i\)向\(b_i\)连一条边,每个环需要大小减\(1\)次操作次数,所以求这张图的最大简单环划分,显然每个环中不会有相同元素,否则可以分裂成\(2\)个小环更优。F1需要构造使最小次数最大的\(b\),那么就是要最小化最大......
  • 软件测试笔记|数据库基础|创建索引的原则
    创建数据库索引有以下原则:一、选择合适的列创建索引1.选择经常用于查询条件的列:如果某一列经常在WHERE子句中作为条件出现,那么为该列创建索引可以大大提高查询速度。例如,在一个员工表中,如果经常根据员工的姓名进行查询,那么为“姓名”列创建索引是一个不错的选择。2.选择......
  • sql手工注入获取库、表名(union联合注入)(个人学习笔记)
    1,发现存在sql漏洞的网站当我们发现一个网站存在sql注入的漏洞时,可以使用sql手工注入来获取信息,如下列的网站sql注入的原理是前端给后端发送指令的时候由于设计者未考虑安全,导致用户可以加上自己的指令进去,从而让服务器完成一些列危险的操作2,确定列表数名首先,我们要先知道......