【SGU 275】 To xor or not to xor

本文介绍一种求解非空子集中元素异或和最大的高效算法。通过从高位到低位枚举二进制位,并利用位操作实现优化选择过程,确保最终得到的异或和为所有可能子集中的最大值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目大意】

给定一个非负整数序列a1,a2,,,an (1<=n<=100,ai<=1018)。要求选出其的一个非空子集,使得异或和最大。求最大异或和。


【分析】

先给出算法,再简略说明正确性。

从高到底枚举每一个二进制位L。

1.找出第L位为1的数ai,如果找到则转2,否则转4.

2.若ans的第L位为0,ans^=ai。

3.使所有第L位为1的数aj^=ai。

4.枚举下一个二进制位。


正确性:

要异或和最大,很明显就是要二进制位从高到低依次尽量填1,上述算法的1,2步就是在干这个事情。

但仅仅这样是不对的,因为第L位为1的可能不止一个数,我们一开始无法判断哪一个更优,怎么办呢?第3步就解决了这个事。

假设序列中有ai,aj,它们第L位都为1。我们先假设ai更优,将ans^=ai。然后执行第3步,aj^=ai。这样就保证了如果aj比ai更优,会在后面的操作中替换掉ai的位置。保证了正确性。

时间复杂度为O(64n2)


【代码】

/* Ciocio's Oi Template */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define ll long long
#define pf printf
#define sf scanf
#define INF (~0U>>3)
#define MAXN 110

int N;
ll A[MAXN];

void Init(){
	cin>>N;
	rep(i,1,N){
		cin>>A[i];
	}
}

void Solve(){
	ll rt=0;
	rrep(i,62,0)
		rep(j,1,N)
			if((A[j]>>i)&1){
				if(!((rt>>i)&1)) rt^=A[j];
				rep(k,1,N)
					if((k!=j)&&((A[k]>>i)&1))
						A[k]^=A[j];
				A[j]=0;
			}
	cout<<rt<<endl;
}

int main(){
	Init();
	Solve();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值