• 线性基入门


    线性基入门

    简要讲解

    1. xor下的线性基:

      线性基求法:
      从高位向低位求,如果控制i位的线性基存在,则a[k]^=p[i]
      否则 p[i] = a[k];break;
      进一步,将除线性基p[i]外的线性基的i位变为0;则得到元素最小的线性基;

    2. 求第k小;
      注意当元素存在冗余,则可以异或生成0;反之,不能生成0
      将k进行2进制表示,则可对应相应的线性基进行异或

    3. 线性基的概念类似于空间张成,即通过最少的元素能张成异或运算下的整个空间

    参考博客

    blog1 blog2

    例题HDU3949

    code
    #include <bits/stdc++.h>
    using namespace std;
    #pragma GCC optimize("O3")
    #define ll long long
    #define ull unsigned long long
    #define db(x) cout<<#x"=["<<(x)<<"]"<<endl
    #define CL(a,b) memset(a,b,sizeof(a))
    #define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define fr0(i,m) for(int i=0;i<m;i++)
    #define fr1(i,m) for(int i=1;i<=m;i++)
    //author:fridayfang
    //date:19 7月 07
    const double esp=1e-8;
    const int mod=1e9+7;
    const double pi=acos(-1);
    const int inf=0x3f3f3f3f;
    const int maxn = 1e4 + 5;
    const int maxm = 1e6+5;
    ll a[maxn];
    ll p[64];
    int to[100];//
    ll t,n,q;
    int getBase(){//处理处理出线性基
        CL(p,0);//先要清0
        for(ll i=1;i<=n;i++){
            for(int j=63;j>=0;j--){
                if((a[i]>>j)&1){
                    if(!p[j]){p[j] = a[i]; break;}
                    a[i]^=p[j];
                }
            }
        }
        // 更小的线性基
        int cnt = 0;
        for(int j=0;j<=63;j++){
            if(!p[j]) continue;
            for(int i=j+1;i<=63;i++){
                if((p[i]>>j)&1) p[i] = p[i]^p[j];
            }
            to[cnt++]=j;
        }
        return cnt;//cnt是线性基的个数 to[0]...to[cnt-1]有正确的映射
    }
    ll getK(ll k,int bound){//除0外的最k小
        int t = 0;
        ll tmp = k;
        ll ans = 0;
        while(tmp){
            if(t>=bound) return -1;
            if(tmp&1) ans^=p[to[t]];
            tmp = tmp>>1;
            t++;
        }
        return ans;
    }
    
    
    
    int main(){
        fast();cin>>t;
        for(ll i=1;i<=t;i++){
            cout<<"Case #"<<i<<":
    ";
            cin>>n;
            for(ll k=1;k<=n;k++) cin>>a[k];
            int cnt = getBase();
            int t = (cnt==(int)n)?0:1;//不等表示有冗余,则可表示0;此时第k小时第k-1小
            cin>>q;
            ll k;
            for(ll s=1;s<=q;s++){
                cin>>k; k-=t;
                cout<<getK(k,cnt)<<endl;
            }
        }
    
        
        return 0;
    }
    
  • 相关阅读:
    ccs元素分类 gcelaor
    webkit Safari的样式库
    “Zhuang.Data”轻型数据库访问框架(二)框架的入口DbAccessor对象
    “Zhuang.Data”轻型数据库访问框架(一)开篇介绍
    一个基于Dapper的DbContext封装
    打造比Dictionary还要快2倍以上的字查找类
    .Net core 的热插拔机制的深入探索,以及卸载问题求救指南.
    字符串类型的自动转换与识别
    最近发现的.net core中的一些bugs
    从项目经理的角度看.net的MVC中Razor语法真的很垃圾.
  • 原文地址:https://www.cnblogs.com/fridayfang/p/11148308.html
Copyright © 2020-2023  润新知