zoukankan      html  css  js  c++  java
  • hdu 3949 XOR (线性基)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=3949

    题意:

    给出n个数,从中任意取几个数字异或,求第k小的异或和

    思路:

    线性基求第k小异或和,因为题目中可以出现异或和为0的情况,但线性基里是不会出现异或和为0的情况,所以我们需要多处理下,将数字全插入到线性基中,如果无法插入也就代表会出现异或和为0的情况,那么求第k小就应该变成求线性基中第k-1小。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 1e6+10;
    struct Linear_Basis{
        ll b[63],nb[63],tot;
        bool flag = 0;
        void init(){
            flag = 0; tot = 0;
            memset(b,-1,sizeof(b));
            memset(nb,0,sizeof(nb));
        }
    
        void Insert(ll x){
            for(int i = 62;i >= 0;i --){
                if(x&(1LL<<i)){
                    if(b[i] == -1){
                        b[i] = x;
                        return ;
                    }
                    x ^= b[i];
                }
            }
            flag = 1;
            return ;
        }
    
        ll Max(ll x){
            ll ret = x;
            for(int i = 62;i >= 0;i --)
                ret = max(ret,ret^b[i]);
            return ret;
        }
    
        ll Min(ll x){
            ll ret = x;
            for(int i = 0;i <= 62;i ++)
                if(b[i]) ret ^= b[i];
            return ret;
        }
    
        void rebuild(){
            for(int i = 62;i >= 0;i --){
                if(b[i] == -1) continue;
                for(int j = i-1;j >= 0;j --){
                    if(b[j] == -1) continue;
                    if(b[i]&(1LL<<j)) b[i]^=b[j];
                }
            }
            for(int i = 0;i <= 62;i ++)
                if(b[i]!=-1) nb[tot++] = b[i];
        }
    
        ll K_Min(ll k){
            ll res = 0;
            if(flag == 1) k --;
            if(k == 0) return 0;
            if(k >= (1LL<<tot))
                return -1;
            for(int i = 62;i >= 0;i --)
                if(k&(1LL<<i))
                    res ^= nb[i];
            return res;
        }
    }LB;
    
    int main()
    {
        int cas = 1,t,n,m;
        cin>>t;
        while(t--){
            LB.init();
            cin>>n;
            ll x;
            for(int i = 1;i <= n;i ++){
                cin>>x;
                LB.Insert(x);
            }
            LB.rebuild();
            printf("Case #%d:
    ",cas++);
            scanf("%d",&m);
            while(m--){
                ll k;
                scanf("%lld",&k);
                printf("%lld
    ",LB.K_Min(k));
            }
        }
        return 0;
    }
  • 相关阅读:
    Win7下VS2010不能链接问题
    10种CSS3实现的Loading效果
    js之事件冒泡和事件捕获及其阻止详细介绍
    JavaScript事件冒泡与捕获
    VUE和ES6资源收集
    vuejs心法和技法
    使用CSS3开启GPU硬件加速提升网站动画渲染性能
    CSS Sprites(CSS图像拼合技术)教程、工具集合
    使用CSS为图片添加更多趣味的5种方法
    使用CSS完美实现垂直居中的方法
  • 原文地址:https://www.cnblogs.com/kls123/p/9745609.html
Copyright © 2011-2022 走看看