HDU 3949 XOR (异或消元)

来源:互联网 发布:奔跑吧兄弟 穿帮知乎 编辑:程序博客网 时间:2024/06/06 18:21

附上链接:hzwer讲的很清楚。
附上秦总博客:秦总

分析:异或消元最后得到的是一组基,那么这些数能够异或出来的值,都是这些基线性组合形成的数,注意,消元以后得到的基是有顺序的(排序以后也能得到顺序),这个时候由于每一位都不可能进位,所以最大的基肯定是第2row小的,row是矩阵的秩。包含0,这个很容易理解,本题的要点就是0能不能取得问题。

附上代码:(其实我是来存代码的,一开始我的xor使用高斯消元的模板写的o(6363n)复杂度,还啰嗦,学习了新的模板,果然不一样!!!o(63n)

代码中注释部分也可以,但是明显发现不如没注释的优美!!!(包含的想法也不太一样,k直接代表了哪几个数可取)

#include <bits/stdc++.h>#define LL long long#define FOR(i,x,y)  for(int i = x;i < y;++ i)#define IFOR(i,x,y) for(int i = x;i > y;-- i)using namespace std;const int maxn = 10010;LL x[maxn];int n,q;int xorguass(LL a[]){    int row = 0;    for(int i = 62;i >= 0;-- i){        int j;        for(j = row;j < n;++ j)    {if(a[j] & (1LL<<i))    break;}        if(j != n){            swap(a[row],a[j]);            for(j = 0;j < n;++ j){                if(j == row)    continue;                if(a[j] && a[j]&(1LL<<i)){                    a[j] ^= a[row];                }            }            ++ row;        }    }    return row;}void work(){    int row = xorguass(x);    LL mx;    if(row < n) mx = 1LL<<row;    else mx = (1LL<<row)-1;    scanf("%d",&q);    while(q --){        LL k;        scanf("%I64d",&k);        if(k > mx)  {printf("-1\n");continue;}        LL ans = 0;        /**        if(row == n)    ++ k;        FOR(i,0,row){            if(!k)  break;            if(k > (1LL<<(row-1-i))){                ans ^= x[i];                k -= (1LL<<(row-1-i));            }        }        **/        if(row < n)    -- k;        FOR(i,0,row)    if(k&(1LL<<(row-1-i))) ans ^= x[i];        printf("%I64d\n",ans);    }}int main(){    //freopen("test.in","r",stdin);    int T,tCase = 0;  scanf("%d",&T);    while(T--){        printf("Case #%d:\n",++tCase);        scanf("%d",&n);        FOR(i,0,n)  scanf("%I64d",&x[i]);        work();    }    return 0;}
0 0
原创粉丝点击