hdu3949-高斯消元法的应用

来源:互联网 发布:linux解压命令zip 编辑:程序博客网 时间:2024/05/15 15:17

题意:  给N个数,从中至少选取1个数的异或值,问第K小的是多少?

用高斯消元法搞基。将N个数化为二进制,求出非线性相关的基。


因为要求最小,则从高位开始消去。


#include<stdio.h>#include<string.h>#include<math.h>#define LL long long#define M 63#define maxN 100000#include<algorithm>using namespace std;int N;LL a[maxN+10];LL d[65];int tot;int ok;void guass(){    int j=1;    for (int i=M-1;i>=0;i--)    {        int k;        for (k=j;k<=N;k++)            if ((a[k]>>i)&1)                break;        if (k==N+1)            continue;        swap(a[k],a[j]);        for (k=1;k<=N;k++)        {            if (k!=j && (a[k]>>i)&1)                a[k] ^= a[j];        }        j++;    }    tot = j-1;    if (j==N+1)        ok = 0;    else        ok = 1; //   for (int i=1;i<=tot;i++)    //    printf("%I64d ",a[i]);   // printf("\n");    return ;}void solve(){    int Q;    scanf("%d",&Q);    while (Q--)    {        LL n;        scanf("%I64d",&n);        if (ok)            n--;        if (n>=d[tot+1])        {            printf("-1\n");            continue;        }        LL rr = 0;        for (int i=tot;i>=1;i--)        {            if (n&1)               rr ^= a[i];            n >>= 1;        }        printf("%I64d\n",rr);    }    return ;}int main(){    d[1]=1;    for (int i=2;i<=63;i++)        d[i]=d[i-1]*2;    int cas,cast= 0;    scanf("%d",&cas);    while (cas--)    {        scanf("%d",&N);        for (int i=1;i<=N;i++)            scanf("%I64d",&a[i]);        printf("Case #%d:\n",++cast);        guass();        solve();    }    return 0;}