hdu3949

线性基?

线性基在我的理解下是一种向量基底,就是说每个数a[i],都能通过线性基组合出来。又因为线性基只有01,所以系数只有01

这道题感觉就是确定每一个二进制位能不能通过xor组合出来,然后因为二进制可以通过贪心确定大小,因为选择最高位肯定是最大的,所以我们可以拆分k来确定每一位选还是不选。

消元之后就能确定每个二进制位是否能选出来,因为高斯消元完了消出一组解,就肯定能通过选或不选某个数组合出来,肯定不会矛盾,比如说两个位是1,他们的组合矛盾了,这是不可能的,因为高斯消元求出了一组方程的解,解肯定满足任意一条方程。

now的意思是能够通过now个元素组合出所有的数,这样的意思也就是有2^now-1个元素,其他的数都是重复。

又理解了一下,就是把每个数消成只有一个1或0个1,0个1选不选无所谓,1个1有选或不选。所以就是选或不选变成了两个数,也就是我们有多少个消完后的a[i]不是0,那么我们就有2^个数-1个不重复的数(0不能出现) 这个东西和向量挺像的。

还有一点不明白...

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10010;
int n, m, now;
ll a[N], bin[70];
void gauss()
{
    now = 1;
    for(int i = 61; i >= 0; --i)
    {
        int j = now;
        while(j <= n && !(a[j] & bin[i])) ++j;
        if(j > n) continue; //这位没有,不能弄出来0
        swap(a[now], a[j]);
        for(int j = 1; j <= n; ++j) if(j != now && a[j] & bin[i]) a[j] ^= a[now];
        ++now; //下一位
    }
    --now; //可以弄出来2^now-1个数
}
ll query(ll k)
{
    ll ret = 0;
    if(now != n) --k;
    if(k >= bin[now]) return -1;
    for(int i = 1; i <= now; ++i) if(k & bin[now - i]) ret ^= a[i];
    return ret;
}
int main()
{
    bin[0] = 1; for(int i = 1; i <= 61 ; ++i) bin[i] = bin[i - 1] << 1;
    int T, cas = 0; scanf("%d", &T);
    while(T--)
    {
        printf("Case #%d:\n", ++cas);
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        gauss();
        scanf("%d", &m);
        while(m--)
        {
            ll k; scanf("%lld", &k);
            printf("%lld\n", query(k));
        }
    }
    return 0;
} 

时间: 2024-10-10 07:50:08

hdu3949的相关文章

【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

给你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 线性基

#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

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(线性基,求第k小的异或和

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 XOR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4731    Accepted Submission(s): 1658 Problem Description XOR is a kind of bit operator, we

[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 线性基模板

Ac链接 给定n个数,求子集异或和的第k大.\(n\le10^5,a_i\le10^9\). 第一步肯定是构造线性基.设线性基的基底数量为k,那么子集异或和本质不同的个数为\(2^k\)(如果有为0的情况).其实求第k大很简单,你把k拆分成2进制,对应基底从左到右的每一位,如果为1就异或上去就行了.不过我们需要分为两种情况,一个是存在异或和为0的情况,一个是不存在的.如果不存在异或和为0,需要把k+1. #include<bits/stdc++.h> #define ll long long