zoukankan      html  css  js  c++  java
  • 线性基

    扯点线性基

    本博客代码未经过测试

    线性基是一个能够在每次时间复杂度(O(log_2d)),d是数字的位数内处理异或最大最小的数据结构。

    问题:请你维护一个数据结构,支持插入一个数,求这些数任意异或得到的结果是否可能为某一个数、最大值、最小值、第k小值。

    做法:开一个数组a[MAXN],MAXN是数字最高位数。

    a[i]表示当前线性基内任意异或出来的数字中,最高位为i的任意一个数字。

    #define MAXN 60
    long long a[64];
    

    插入x|判断x是否存在

    从高位到低位枚举所有位数,如果x的第i位有值:如果a[i]不存在,则a[i]=x,并退出。如果a[i]存在,令x^=a[i]。如果最后x变成了0,那么说明x在线性基内。

    bool insert(long long x)
    {
        for(int i = MAXN; i >= 0; i--)
        {
            if(x & (1LL << i))
            {
                if(a[i] == 0)
                {
                    a[i] = x;
                    break;
                }
                x ^= a[i];
            }
        }
        return x > 0;
    }
    

    查询最大值

    从高位到低位扫描线性基。如果异或之后答案变大,就把这一位异或到答案。

    long long getmax()
    {
        long long ans = 0;
        for(int i = MAXN; i >= 0; i--)
        {
            if((ans ^ a[i]) > ans)
                ans ^= a[i];
        }
        return ans;
    }
    

    查询最小值

    从低位到高位扫描线性基。最低位上的线性基即为答案。

    long long getmin()
    {
        for(int i = 0; i <= MAXN; i++)
        {
            if(a[i] > 0)
                return a[i];
        }
    }
    

    第k小

    首先我们要改造一下线性基。我们把线性基改造成每一位相互独立,意思就是对于第i位,线性基上只有一个未知的第i位可能是1。具体如何改造,就是从高位向低位扫描,对于第i位线性基a[i],对于j<i,如果a[i]的第j位是1,就让a[j]异或上a[i]。

    查询的时候,将k进行二进制拆分,对于的1位,就异或对应的线性基。

    最终得到的答案是第k小值。

    int p[64],cnt;
    void rebuild()
    {
    	for(int i = MAXN; i >= 0; i--)
        {
            for(int j = i - 1; j >= 0; j--)
                if(a[i] & (1LL << j))
                    a[i] ^= a[j];
        }
        for(int i = 0; i <= MAXN; i++)
        {
            if(a[i])
                p[cnt++]=d[i];
        }
    }
    
    long long query(long long k)
    {
        long long ans=0;
        rebuild();
        if(k >= (1LL << cnt))
        	return -1;
        for(int i = MAXN; i >= 0; i--)
        {
            if(k & (1LL << i))
                ans ^= p[i];
        }
        return ans;
    }
    
  • 相关阅读:
    数独
    面向对象程序设计课第七次作业
    面向对象程序设计课第六次作业
    软件工程课总结
    第四次作业:四则运算界面
    psp记录个人项目花费时间
    作业三:代码规范,代码复查
    编写一个能生成小学四则运算题目的运算
    目前流行的源程序版本管理软件和项目管理软件有哪些?有什么优缺点
    课程进度总结
  • 原文地址:https://www.cnblogs.com/oier/p/9596789.html
Copyright © 2011-2022 走看看