zoukankan      html  css  js  c++  java
  • 线性基学习笔记

    线性基

    最近刚学习了一个叫线性基的东西.
    还是很有意思的.

    线性基的性质

    线性基有一些很妙的性质.

    • 线性基是一个(x)维向量(a_1,a_2,a_3...a_x),其中(a_i)最高位的(1)在第(i)位上.
    • 由线性基中的数异或出来的数值域和原来的数异或和值域相同.

    线性基的构造

    插入一个数(x)时,从最高位向最低位扫,如果这一位上线性基为空,那么就插入.否则就让(x)异或上这一位的数.

    线性基求最大值

    从高位往低位扫,如果异或上这一位使答案变大,那么异或.

    线性基判断是否出现

    从高位往低位扫,如果(x)这一位是(1),那么异或上这一位.

    线性基求第(k)小值

    首先先重构一下线性基.
    如果(i<j,a_j)的第(i)位是(1),那么让(a_j)异或上(a_i).
    那么只有(a_i)的第(i)位是(1),其他都是(0).
    我们称重构后的线性基为(b)
    查询时,如果(k)的第(i)位是(1),就异或上(b_i)

    下面是封装的线性基

    struct LB{
    	bool flag;
    	LL a[N],b[N];
    	int cnt; 
    	void clear(){
    		memset(a,0,sizeof(a)),flag=0;
    		memset(b,0,sizeof(b)),cnt=0;
    	} 
    	void insert(LL x){
    		bool ins=0;
    		for(int i=62;i>=0;i--){
    			if(!((x>>(LL)i)&1ll))continue;
    			if(!a[i]){a[i]=x,ins=1;break;}
    			x^=a[i];
    		}
    		if(!ins)flag=1;
    	}
    	LL getmax(){
    		LL ans=0;
    		for(int i=62;i>=0;i--)
    		if(ans<(ans^a[i]))ans^=a[i];
    		return ans;
    	}
    	bool exist(LL x){
    		if(!x)return flag;
    		for(LL i=62;i>=0;i--)
    		if((x>>i)&1)x^=a[i];
    		return x?0:1;
    	}
    	void rebuild(){
        	for(LL i=62;i>=0;i--)
        	for(LL j=i-1;j>=0;--j)
            if((a[i]>>j)&1)a[i]^=a[j];
        	for(LL i=0;i<=62;++i)if(a[i])b[cnt++]=a[i];
    	}
    	LL query_kth(LL k){
    		if(flag)if(!(--k))return 0;
        	if(k>=(1ll<<cnt))return -1; 
    		LL ans=0;
        	for(LL i=62;i>=0;--i)
        	if((k>>i)&1)ans^=b[i];
        	return ans;
    	}
    }S;
    

    例题

    首先来几道模板题
    (Luogu3812)
    (HDU3969)

    接下来是一道简单题
    (BZOJ2460)
    只要先按(v)从大到小排序,然后每次看看是否能插入(num),如果可以,答案就加上(v)即可.

    接下来是一道稍难题
    (BZOJ2115)
    详细题解戳这里

  • 相关阅读:
    模型定义
    聚合、原生和子查询
    PHP curl扩展
    时间查询
    查询表达式
    HTTP协议的Keep-Alive 模式
    抽象类可以没有抽象方法
    Nginx解决前端跨域问题,Nginx反向代理跨域原理
    Nginx配置文件不生效,Nginx配置文件重启也不生效
    php openssl加密解密函数
  • 原文地址:https://www.cnblogs.com/Romeolong/p/10062637.html
Copyright © 2011-2022 走看看