HDU3949 线性基模板

Posted kgxw0430

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3949 线性基模板相关的知识,希望对你有一定的参考价值。

Ac链接


  • 给定n个数,求子集异或和的第k大。(nle10^5,a_ile10^9)
  • 第一步肯定是构造线性基。设线性基的基底数量为k,那么子集异或和本质不同的个数为(2^k)(如果有为0的情况)。其实求第k大很简单,你把k拆分成2进制,对应基底从左到右的每一位,如果为1就异或上去就行了。不过我们需要分为两种情况,一个是存在异或和为0的情况,一个是不存在的。如果不存在异或和为0,需要把k+1。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100;
ll t,n,m,q,cnt,k,ans,a[N];
void insert(ll v){
    for(int i=63;i>=0;--i) if((v>>i)&1){
        if(a[i]) v^=a[i];
        else{
            for(int j=i-1;j>=0;--j)
                if((v>>j)&1) v^=a[j];
            for(int j=i+1;j<=63;++j)
                if((a[j]>>i)&1) a[j]^=v;
            a[i]=v;
            break;
        }
    }
}
int main(){
    scanf("%lld",&t);
    for(int cas=1;cas<=t;++cas){
        memset(a,0,sizeof(a));
        scanf("%lld",&n);ll x;
        for(int i=1;i<=n;++i){
            scanf("%lld",&x);
            insert(x);
        }
        cnt=0;
        for(int i=0;i<=63;++i) if(a[i]) cnt++;
        scanf("%lld",&m);
        printf("Case #%d:
",cas);
        for(int i=1;i<=m;++i){
            scanf("%lld",&k);
            if(cnt==n) k++;
            ll ans=0;ll tmp=cnt;
            if(k>(1LL<<cnt)){printf("-1
");continue;}
            for(int i=63;i>=0;--i){
                if(a[i]){
                    ll now=1LL<<(tmp-1);
                    if(k>now) k-=now,ans^=a[i];
                    tmp--;
                }
            }
            printf("%lld
",ans);
        }
    }
    return 0;
}

以上是关于HDU3949 线性基模板的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3949 XOR (线性基,模板)

HDU3949 线性基模板

[hdu3949]XOR(线性基求xor第k小)

HDU3949 XOR

hdu 3949 XOR (线性基)

HDU - 3949 :XOR(线性基)