HDU3949 XOR

线性基模板

线性基可以看成把一组序列处理过后得到的新数组,他和原序列异或和的值域完全相同,也就是说原序列的任意几个数的异或和都可以被线性基的数表示出来,因此线性基可以看成数原序列的替代。

我们通过特殊的方法处理出线性基,可以快速求出原序列中异或和最大的子集,以及第k小的子集。

存一下自己的板子

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long LL;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int ret = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        ret = (ret << 3) + (ret << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -ret : ret;
}
inline int lcm(int a, int b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}

const int N = 20005;
int _, n, m, cnt, k, cs;
LL val, b[N], a[N];
void insert(LL x){
    for(int i = 62; i >= 0; i --){
        if(x & (1LL << i)){
            if(!b[i]){
                b[i] = x;
                break;
            }
            else x ^= b[i];
        }
    }
}

LL maximum(){
    LL ret = 0;
    for(int i = 62; i >= 0; i --){
        if((ret ^ b[i]) > ret) ret ^= b[i];
    }
    return ret;
}

LL minimum(){
    for(int i = 0; i<= 62; i ++){
        if(b[i]) return b[i];
    }
}

void rebuild(){
    full(a, 0), cnt = 0;
    for(int i = 62; i >= 0; i --){
        for(int j = i - 1; j >= 0; j --)
            if(b[i] & (1LL << j)) b[i] ^= b[j];
    }
    for(int i = 0; i <= 62; i ++){
        if(b[i]) a[cnt++] = b[i];
    }
}

LL query(int k){
    if(k >= (1LL << cnt)) return -1;
    LL ret = 0;
    for(int i = 62; i >= 0; i --){
        if(k & (1LL << i)) ret ^= a[i];
    }
    return ret;
}

int main(){

    for(scanf("%d", &_); _; _ --){
        full(b, 0);
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            scanf("%lld", &val);
            insert(val);
        }
        rebuild();
        scanf("%d", &m);
        printf("Case #%d:\n", ++cs);
        while(m --){
            scanf("%d", &k);
            if(n != cnt) k --;
            printf("%lld\n", query(k));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/onionQAQ/p/11230807.html

时间: 2024-11-11 23:08:48

HDU3949 XOR的相关文章

【线性基】hdu3949 XOR

给你n个数,问你将它们取任意多个异或起来以后,所能得到的第K小值? 求出线性基来以后,化成简化线性基,然后把K二进制拆分,第i位是1就取上第i小的简化线性基即可.注意:倘若原本的n个数两两线性无关,也即线性基的大小恰好为n时,异或不出零,否则能异或出零,要让K减去1. 这也是线性基的模板. #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll d[64],p[64]; int

hdu3949 XOR xor高斯消元

XOR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1364    Accepted Submission(s): 402 Problem Description XOR is a kind of bit operator, we define that as follow: for two binary base number A

HDU3949 XOR(线性基第k小)

Problem Description XOR is a kind of bit operator, we define that as follow: for two binary base number A and B, let C=A XOR B, then for each bit of C, we can get its value by check the digit of corresponding position in A and B. And for each digit,

[hdu3949]XOR(线性基求xor第k小)

题目大意:求xor所有值的第k小,线性基模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int MAX_BASE=63; ll base[64],a[10006]

线性基 刷题记录

HDU3949 XOR 线性基板子题 给定一些数 求这些数能通过异或得到的第k大的值. 代码: 1 #include <bits/stdc++.h> 2 #define nmax 10010 3 4 using namespace std; 5 typedef long long ll; 6 ll a[nmax],b[70],k[70]; //k[i] 第i小的数 7 int n,q; 8 9 int main(){ 10 //freopen("owo.in","

【HDU3949】XOR

[题目大意] 给定一个数组,求这些数组通过异或能得到的数中的第k小是多少. 传送门:http://vjudge.net/problem/HDU-3949 [题解] 首先高斯消元求出线性基,然后将k按照二进制拆分即可. 注意当高斯消元结束后若末尾有0则第1小是0 特判一下然后k--. 然后HDU输出long long是用%I64d 无论C++还是G++都是.(虽然我用了lld也AC了) 1 #include<iostream> 2 #include<cstdio> 3 #includ

【HDU3949】XOR 线性基

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43448493"); } 题意:给若干个数让你异或,然后询问第k大的异或和. 题解: 先搞出来线性基,然后第k大的异或和就是: 把k二进制拆分,第i位上有1,就把第i个线性基异或进来. 原因: 因为线性基是一堆高位上的1(或许有一些位动不了),然后把这

HDU3949:XOR——题解

http://acm.hdu.edu.cn/showproblem.php?pid=3949 求n个数的异或和第k小. 参考:https://blog.sengxian.com/algorithms/linear-basis 没了. #include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<algorithm> using namespace s

bzoj 2337: [HNOI2011]XOR和路径

Description Input Output Sample Input Sample Output HINT Source Day2 终于把这个史前遗留的坑给填了... 首先异或的话由位无关性,可以按位处理... 那么对于每一位,设f[i]表示从i出发第一次到达n且xor和为1的概率,out[i]为i的出边,那么转移就比较容易了... if(w(i,j)&xxx) f[i]+=(1-f[j)/out[i];// 这条边该位为1,需要xor上0,xor和才为1 else f[i]+=f[j]/