码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3949 XOR (线性基)

时间:2018-10-05 19:44:57      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:style   set   ble   while   its   插入   pre   php   continue   

链接: 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:\n",cas++);
        scanf("%d",&m);
        while(m--){
            ll k;
            scanf("%lld",&k);
            printf("%lld\n",LB.K_Min(k));
        }
    }
    return 0;
}

 

hdu 3949 XOR (线性基)

标签:style   set   ble   while   its   插入   pre   php   continue   

原文地址:https://www.cnblogs.com/kls123/p/9745609.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!