zoukankan      html  css  js  c++  java
  • HDU_3949 XOR 【线性基】

    一、题目

      XOR

    二、分析

      给定$N$个数,问它的任意子集异或产生的数进行排列,求第K小的数。

      构造出线性基$B$后,如果$|B| < N$,那么代表N个数中有一个数是可以由线性基中的其他数异或出来的,那么相当于可以异或出$0$。也就是说这种情况下会多一个0作为最小数。

      然后对于第$K$大,可以直接对$K$的二进制进行判断,如果为$1$就取线性基对应的数,然后进行异或就可以得出答案了。

    三、AC代码

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define ll long long
     5 #define Min(a,b) ((a)>(b)?(b):(a))
     6 #define Max(a,b) ((a)>(b)?(a):(b))
     7 const int maxn = 1e4 + 13;
     8 const int maxl = 62;
     9 ll a[maxn];
    10 
    11 struct LinerBasis
    12 {
    13     vector<ll> vec;
    14     int n;
    15 
    16     void build(ll *x, int n)
    17     {
    18         this->n = n;
    19         vector<ll> a(maxl+1);
    20         for(int i = 1; i <= n; i++)
    21         {
    22             ll t = x[i];
    23             for(int j = maxl; j >= 0; j--)
    24             {
    25                 if( (t & (1ll<<j)) == 0 )
    26                     continue;
    27                 if(a[j])
    28                     t^=a[j];
    29                 else
    30                 {
    31                     //将低位的已存在的a[k],异或消掉t的这一位1
    32                     //a[k]=0也没有影响
    33                     for(int k = 0; k < j; k++)
    34                     {
    35                         if(t & (1ll<<k))
    36                             t ^= a[k];
    37                     }
    38                     //消除高位上a[k]的第j位1
    39                     for(int k = j + 1; k <= maxl; k++)
    40                     {
    41                         if(a[k] & (1ll << j))
    42                             a[k] ^= t;
    43                     }
    44                     a[j] = t;
    45                     break;
    46                 }
    47             }
    48         }
    49         vec.clear();
    50         for(int i = 0; i <= maxl; i++)
    51         {
    52             if(a[i])
    53                 vec.push_back(a[i]);
    54         }
    55     }
    56 
    57     ll query(ll K)
    58     {
    59         //可能异或出0
    60         if(vec.size() < n)
    61             K--;
    62         if(K > (1ll<<vec.size()) - 1)
    63             return -1;
    64         ll ans = 0;
    65         for(int i = 0; i < vec.size(); i++)
    66         {
    67             if(K & (1ll << i))
    68             {
    69                 ans ^= vec[i];
    70             }
    71         }
    72         return ans;
    73     }
    74 
    75 }lb;
    76 
    77 int main()
    78 {
    79     int T, Case = 0;
    80     scanf("%d", &T);
    81     while(T--)
    82     {
    83         int N, Q;
    84         scanf("%d", &N);
    85         for(int i = 1; i <= N; i++) scanf("%lld", &a[i]);
    86 
    87         lb.build(a, N);
    88 
    89         scanf("%d", &Q);
    90         ll K;
    91         printf("Case #%d:
    ", ++Case);
    92         while(Q--)
    93         {
    94             scanf("%lld", &K);
    95             printf("%lld
    ", lb.query(K));
    96         }
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    慢性肾炎患者的家庭养护
    中国居民五谷膳食指南
    第二单元丨对环境的察觉
    一个人是否靠谱,闭环很重要
    打赢营销胜仗
    治本修身──中醫內分泌調節養生法
    理想的激励
    卓越演讲:打动听众必知必会的策略和方法(原书第3版)
    每日一题_191008
    每日一题_191007
  • 原文地址:https://www.cnblogs.com/dybala21/p/11366699.html
Copyright © 2011-2022 走看看