zoukankan      html  css  js  c++  java
  • 线性基的一些基础模版

    大神博客:https://blog.csdn.net/a_forever_dream/article/details/83654397

    线性基三大性质

    1.原序列里面的任意一个数都可以由线性基里面的一些数异或得到

    2.线性基里面的任意一些数异或起来都不能得到0

    3.线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的

    插入操作:

    void add(ll x)
    {
        for(int i=50;i>=0;i--)
        {
            if(x&(1ll<<i))//注意,如果i大于31,前面的1的后面一定要加ll
            {
                if(d[i])x^=d[i];
                else
                {
                    d[i]=x;
                    break;//记得如果插入成功一定要退出. 
                }
            }
        }
        //插入失败
    }

    求最大值:

    完整的说,是如何求在一个序列中,取若干个数,使得它们的异或和最大。
    首先构造出这个序列的线性基,然后从线性基的最高位开始,假如当前的答案异或线性基的这个元素可以变得更大,那么就异或它,答案的初值为0

    要优先使最高位尽可能大

    ll getmax()
    {
        ll anss=0;
        for(int i=50;i>=0;i--)//记得从线性基的最高位开始
            if((anss^d[i])>anss)anss^=d[i];
        return anss;
    }

    求第k小的值

    void work()//处理线性基
    {
        for(int i=1;i<=60;i++)
            for(int j=1;j<=i;j++)
                if(d[i]&(1<<(j-1)))d[i]^=d[j-1];
    }
    ll k_th(ll k)
    {
        if(k==1&&tot<n)return 0;//特判一下,假如k=1,并且原来的序列可以异或出0,就要返回0,tot表示线性基中的元素个数,n表示序列长度
        if(tot<n)k--;//类似上面,去掉0的情况,因为线性基中只能异或出不为0的解
        work();
        ll ans=0;
        for(int i=0;i<=60;i++)
            if(d[i]!=0)
            {
                if(k%2==1)ans^=d[i];
                k/=2;
            }
        return ans;
    }
  • 相关阅读:
    JSP中<base href="<%=basePath%>">作用
    转 jdk1.5新特性 ConcurrentHashMap
    单例设计模式与类加载顺序详解
    归并排序-java
    插入排序-java
    冒泡排序-java
    选择排序-java
    JS的object数据类型
    JS的事件
    JS的捕捉回车键
  • 原文地址:https://www.cnblogs.com/smallhester/p/11415311.html
Copyright © 2011-2022 走看看