HDU_3949 XOR gauss

来源:互联网 发布:斗鱼大官人淘宝店网址 编辑:程序博客网 时间:2024/04/30 13:39

http://acm.hdu.edu.cn/showproblem.php?pid=3949

题意:

给你N个数,要你从中取出若干个进行异或运算,求最后所有可以得到的异或结果中的

第k小的异或值。N<=10^18

思路:

首先以位数为行,N和数为列,建一个矩阵,然后就对矩阵进行高斯消元,消元之后这

N个数异或的结果就可以用一组线性基来表示了,该线性基的下标编号就是异或值的大

小标号,因此本题就可以得出解了。

代码;

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;typedef unsigned __int64 LL ;int N ,Q ;const int NN = 10000 + 10 ;const int MM = 63 ;LL a[NN] ;int ans[MM] , f[MM] ,SS , tot ;bool ok ;LL d[MM] ;void gauss(){    int row, col ,i , j , k;    j = 0 ;    for(row=MM-1;row>=0;row--){        for(k=j;k<N;k++){            if( (a[k]>>row)&1 ) break ;        }        if( k == N )    continue ;        swap( a[k] , a[j] ) ;        for(int i=0;i<N;i++){            if( i!=j && (( a[i]>>row)&1 ) ){                a[i] ^= a[j] ;            }        }        j++ ;    }    tot = j ;    if(j == N)  ok = 0 ;    else        ok = 1 ;}void solve(){    LL aa ;    scanf("%d",&Q);    for(int i=0;i<Q;i++){        scanf("%I64u",&aa);        if( ok  ) aa-- ;        if( aa >= d[tot] ){            printf("-1\n"); continue ;        }        LL rr = 0 ;        for(int i=tot-1;i>=0;i--){            if(aa&1) rr ^= a[i] ;            aa >>= 1 ;        }        printf("%I64u\n" , rr );    }}int main(){    d[0] = 1 ;    for(int i=1;i<MM;i++) d[i] = d[i-1] * 2 ;    int ccas, cas ;    for(scanf("%d",&ccas), cas=1;cas<=ccas;cas++){        scanf("%d",&N);        for(int i=0;i<N;i++)    scanf("%I64u",&a[i]);        gauss() ;        printf("Case #%d:\n",cas) ;        solve() ;    }    return 0 ;}

原创粉丝点击