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;
    }
    
    
  • 相关阅读:
    2018ACM上海大都会赛 F Color it【基础的扫描线】
    2018大都会赛 A Fruit Ninja【随机数】
    两个数互质的概率
    【shell脚本学习-3】
    【mysql学习-1】
    【HCNE题型自我考究】
    【为系统营造的一个安全的环境】
    【nginx下对服务器脚本php的支持】
    【linux基于Postfix和Dovecot邮件系统的搭建】
    不同状态的动态路由协议对比
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11236453.html
Copyright © 2011-2022 走看看