【YBT2023寒假Day9 A】异或路径(线性基)

异或路径

题目链接:YBT2023寒假Day9 A

题目大意

有一个 n*m 的网格,然后你要从 (1,1) 走到 (n,m),你的分数是你路径上每个点的权值的异或和(出现多次就异或多次)。
每次可以选上下左右四个方向走,不能走出网格,问你分数最大值。

思路

首先如果只能向右向下走你走的点的个数是确定是 n+m1
考虑在这个基础上加一些修改,会发现你如果要改一段路径,你把那一段的路径,和你要改成的路径,它形成一个圈,那你直接异或上这个圈的值,就可以改路径了。

那么这样的话,我们其实可以直接控制任意个数是否出现。
但是其实是错的,你会注意到个数不是任意的。
考虑每个圈的长度都是偶数,而且有相同位置就消去每次也是消除 2 个(偶数个),所以你无论怎么变换,个数的奇偶性都是 n+m1 的奇偶性。

于是考虑如何让线性基选的数量的奇偶性固定。
于是考虑让选奇数个更优或者偶数个更优。
那联系上异或的性质,对于选奇数个我们可以给每个数赋一个很大的二次方值(比如 245),然后再丢进去跑线性基,出来的结果异或一下这个值即可。
那对于偶数,那你就在跑最大值的时候一开始是这个很大的数,就跟奇数一样了。

代码

#include<cstdio> #define ll long long using namespace std; const int N = 5e5 + 100; int n, m, tot; ll a[N]; struct XXJ { ll f[64]; void insert(ll x) { for (int i = 63; i >= 0; i--) if ((x >> i) & 1) { if (!f[i]) { f[i] = x; break; } x ^= f[i]; } } ll get_max(ll fir) { for (int i = 63; i >= 0; i--) { if (!((fir >> i) & 1)) fir ^= f[i]; } return fir; } }p; int main() { freopen("xor.in", "r", stdin); freopen("xor.out", "w", stdout); scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%lld", &a[++tot]), a[tot] ^= (1ll << 45), p.insert(a[tot]); if (!((n + m - 1) & 1)) printf("%lld", p.get_max(1ll << 45) ^ (1ll << 45)); else printf("%lld", p.get_max(0ll) ^ (1ll << 45)); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/YBT2023Day9_A.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-02-08 【YBT2022寒假Day3 C】毒瘤染色(LCT)(圆方树)(容斥)
2022-02-08 【YBT2022寒假Day3 B】【LOJ 2460】欧拉回路 / 桥(二分)(欧拉回路)(网络流)
2022-02-08 【YBT2022寒假Day3 A】森林之和(prufer序列)(DP)
2021-02-08 GDKOI2021 爆炸记
点击右上角即可分享
微信分享提示