HDU 3949 XOR [高斯消元XOR 线性基]

本文介绍了一个名为“3949冰上走”的算法问题,该问题要求从给定的整数集合中选取若干个数进行异或运算,并找出所有可能结果中的第k小值。通过使用高斯消元法确定线性基,可以有效地解决这个问题。当给定的k值超出可能的结果范围时,问题无解。

3949冰上走


题意:

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


N个数高斯消元求出线性基后,设秩为$r$,那么总共可以组成$2^r$中数字(本题不能不选,所以$2^r -1$)

然后如果$k \ge 2^r$就不存在啦

否则一定可以有$k$小,因为现在$1..r$行每行都有一位是1(左面是最高位)

从高到低枚举k的二进制,如果是1就异或上对应的行就行了,最后就是k小值啦

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;
typedef long long ll;
const int N=1e4+5,INF=1e9;
inline ll read(){
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n,Q;
ll a[N],k,bin[N];
void ini(){
    bin[0]=1;for(int i=1;i<=60;i++) bin[i]=bin[i-1]<<1;
}    
int now;
void Gauss(){
    now=1;
    for(int i=60;i>=0;i--){
        int j=now;
        while(j<=n&&!(a[j]&bin[i])) j++;
        if(j==n+1) continue;
        if(j!=now) swap(a[j],a[now]);
        for(int k=1;k<=n;k++) 
            if(k!=now&&(a[k]&bin[i])) a[k]^=a[now];
        now++;
    }
    now--;
}
ll Query(ll k){//printf("Q %lld\n",k);
    ll ans=0;
    if(now!=n) k--;
    if(k>=bin[now]) return -1;
    for(int i=1;i<=now;i++)
        if(k&bin[now-i]) ans^=a[i];
    return ans;
}
int main(){
    freopen("in","r",stdin);
    ini();
    int T=read(),cas=0;
    while(T--){printf("Case #%d:\n",++cas);
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        Gauss();
        Q=read();
        while(Q--) printf("%lld\n",Query(read()));
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值