zoukankan      html  css  js  c++  java
  • HDU 3949 XOR (线性基第k小)题解

    题意:

    给出(n)个数,求出子集异或第(k)小的值,不存在输出-1。

    思路:

    先用线性基存所有的子集,然后对线性基每一位进行消元,保证只有(d[i])(i)位存在1,那么这样变成了一组基线性基,然后按(k)的二进制找地k小。因为线性基不保存0,所以对有0的情况要进行特判。

    代码:

    #include<map>
    #include<set>
    #include<cmath>
    #include<cstdio>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 1000 + 5;
    const int INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    struct Liner_Basis{
        ll d[63], nd[63];
        int tot, flag;
        void init(){
            memset(d, 0, sizeof(d));
            memset(nd, 0, sizeof(nd));
            tot = flag = 0;
        }
        bool insert(ll x){
            for(int i = 62; i >= 0; i--){
                if(x & (1LL << i)){
                    if(d[i]) x ^= d[i];
                    else{
                        d[i] = x;
                        return true;
                    }
                }
            }
            flag = 1;
            return false;
        }
        void rebuild(){
            for(int i = 62; i >= 0; i--){
                if(d[i] == 0) continue;
                for(int j = i - 1; j >= 0; j--){
                    if(d[i] & (1LL << j)) d[i] ^= d[j];
                }
            }
            for(int i = 0; i <= 62; i++){
                if(d[i]) nd[tot++] = d[i];
            }
        }
        ll kth_min(ll k){
            if(flag) k--;
            if(k == 0) return 0;
            if(k >= (1LL << tot)) return -1;
            ll ret = 0;
            for(int i = 62; i >= 0; i--){
                if(k & (1LL << i)){
                    ret ^= nd[i];
                }
            }
            return ret;
        }
    }lb;
    int main(){
        int T, ca = 1;
        scanf("%d", &T);
        while(T--){
            int n;
            ll x;
            scanf("%d", &n);
            lb.init();
            for(int i = 1; i <= n; i++){
                scanf("%lld", &x);
                lb.insert(x);
            }
            lb.rebuild();
            int q;
            scanf("%d", &q);
            printf("Case #%d:
    ", ca++);
            while(q--){
                scanf("%lld", &x);
                printf("%lld
    ", lb.kth_min(x));
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    数据结构第四篇——线性表的链式存储之双向链表
    基本概念之引用赋值需要注意什么?
    基本概念之将引用作为函数的参数有哪些特点?
    基本概念之什么是引用?
    基本概念之模板类有什么优势?
    我的第一篇博文
    为CentOS 6 配置本地YUM源
    为CentOS 6 配置本地YUM源
    poj 1990 MooFest
    [置顶] 学生信息管理系统“重复设置”问题
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11236453.html
Copyright © 2011-2022 走看看