hdu 3949 XOR (线性基)

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

题意:

给出n个数,从中任意取几个数字异或,求第k小的异或和

思路:

线性基求第k小异或和,因为题目中可以出现异或和为0的情况,但线性基里是不会出现异或和为0的情况,所以我们需要多处理下,将数字全插入到线性基中,如果无法插入也就代表会出现异或和为0的情况,那么求第k小就应该变成求线性基中第k-1小。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e6+;
struct Linear_Basis{
ll b[],nb[],tot;
bool flag = ;
void init(){
flag = ; tot = ;
memset(b,-,sizeof(b));
memset(nb,,sizeof(nb));
} void Insert(ll x){
for(int i = ;i >= ;i --){
if(x&(1LL<<i)){
if(b[i] == -){
b[i] = x;
return ;
}
x ^= b[i];
}
}
flag = ;
return ;
} ll Max(ll x){
ll ret = x;
for(int i = ;i >= ;i --)
ret = max(ret,ret^b[i]);
return ret;
} ll Min(ll x){
ll ret = x;
for(int i = ;i <= ;i ++)
if(b[i]) ret ^= b[i];
return ret;
} void rebuild(){
for(int i = ;i >= ;i --){
if(b[i] == -) continue;
for(int j = i-;j >= ;j --){
if(b[j] == -) continue;
if(b[i]&(1LL<<j)) b[i]^=b[j];
}
}
for(int i = ;i <= ;i ++)
if(b[i]!=-) nb[tot++] = b[i];
} ll K_Min(ll k){
ll res = ;
if(flag == ) k --;
if(k == ) return ;
if(k >= (1LL<<tot))
return -;
for(int i = ;i >= ;i --)
if(k&(1LL<<i))
res ^= nb[i];
return res;
}
}LB; int main()
{
int cas = ,t,n,m;
cin>>t;
while(t--){
LB.init();
cin>>n;
ll x;
for(int i = ;i <= n;i ++){
cin>>x;
LB.Insert(x);
}
LB.rebuild();
printf("Case #%d:\n",cas++);
scanf("%d",&m);
while(m--){
ll k;
scanf("%lld",&k);
printf("%lld\n",LB.K_Min(k));
}
}
return ;
}
上一篇:php之PDO连接mysql数据库,增删改查等等操作实例


下一篇:打开文件对话框在xp和win7上的实现文件任意多选