hdu 3949 (线性基学习)

来源:互联网 发布:840dsl调试软件 编辑:程序博客网 时间:2024/06/06 15:47

题意:给N个数, 求异或和第k大的数


线性基:高斯消元构造对角矩阵,具体理论证明看其他详细介绍


把k二进制拆分,第i位上有1,就把第i个线性基异或进来。
原因:
因为线性基是一堆高位上的1(或许有一些位动不了),然后把这样每一位可以填0/1,跟二进制差不多,第i位为1时取当前行的矩阵值,就能得到第k大的值了


注意:输出lld会wa,输出I64u


#include <iostream>#include <string.h>using namespace std;#define ll unsigned long long#define M 63int n;ll dat[10005],flag,tot;ll mt[70];void gauss(){    memset(mt,0,sizeof(mt));    ll i,j,k,r;    flag=0;    for(i=1;i<=n;i++)    {        for(j=M;~j;j--)        {            if( (dat[i]>>j)&1 )                if( !mt[j] )                {                    mt[j]=dat[i];                    for(k=0;k<=M;k++)                        for(r=k+1;r<=M;r++)                            if( (mt[r]>>k)&1 )                                mt[r]^=mt[k];                    break;                }                else dat[i]^=mt[j];        }        if( dat[i]==0) flag=1;    }}int main(){    int T,t,m;    ll i,q;    scanf("%d",&T);    for(t=1;t<=T;t++)    {        scanf("%d",&n);        for(i=1;i<=n;i++)            scanf("%I64u",&dat[i]);        gauss();        for(i=0,tot=0;i<=M;i++)            if(mt[i])                mt[tot++]=mt[i];        printf("Case #%d:\n",t);         scanf("%d",&m);        while(m--)        {            scanf("%I64u",&q);            ll ans=0;            q-=flag;            if(q==0)                printf("0\n");        else if( q>>tot )                printf("-1\n");        else         {            for(i=0;i<tot;i++)            {                if((q>>i)&1)                    ans^=mt[i];            }                            printf("%I64u\n",ans);        }        }    }    return 0;}


原创粉丝点击