【CLYZ集训】异或路径【线性基】

119 篇文章 0 订阅

题目大意

给一个 n × m n\times m n×m的网格,然后从 ( 1 , 1 ) (1,1) (1,1)走到 ( n , m ) (n,m) (n,m)处。每次可往上下左右四个方向走。问走过路径上的数的异或和最大是多少。(走到 ( n , m ) (n,m) (n,m)处不一定要结束)

思路:

推演发现,这题选择的数的个数的奇偶和 n + m − 1 n+m-1 n+m1的奇偶相同,而想选里面任意一个数都是没问题的。
所以考虑奇数的情况,每个数加一个很大的2次幂,这就保证了要选奇数个数。
偶数的情况就是在线性基里面多加一个由两个很大的2次幂构成的数,这就保证了这个数必须被选,然后转化为奇数的情况。

c o d e code code

#include<iostream>
#include<cstdio>
#include<vector>
#define ll long long

using namespace std;

ll n, m;
ll d[61];

void add(ll x) {
	for(ll i = 60; i >= 0; i --)
		if(x & (1ll << i)) {
			if(d[i]) x ^= d[i];
			else {
				d[i] = x;
				break;
			}
		}
}

ll ans() {
	ll ANS = 0;
	for(ll i = 60; i >= 0; i --)
		if((ANS ^ d[i]) >= ANS) ANS ^= d[i];
	return ANS;
}

int main() {
	freopen("xor.in", "r", stdin);
	freopen("xor.out", "w", stdout);
	scanf("%lld%lld", &n, &m);
	for(ll i = 1; i <= n; i ++)
		for(ll j = 1; j <= m; j ++) {
			ll x;
			scanf("%lld", &x);
			add(x + (1ll << 34));
		}
	if((n + m - 1) % 2 == 0) {
		add((1ll << 34) + (1ll << 33));
		printf("%lld", ans() - ((1ll << 34) + (1ll << 33)));
	}
	else {
		printf("%lld", ans() - (1ll << 34));
	}
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值