传送门

题意:

给出\(n\)个数\(a_i\),现在要将其分为两堆,使得这两堆数的异或和相加最大。

思路:

  • 考虑线性基贪心求解。
  • 但直接上线性基求出一组的答案是行不通的,原因之后会说。
  • 注意到如果二进制中某一位\(1\)的个数出现了奇数次,那么无论怎么分,都会有一组中这位为\(1\);对于出现偶数次的位,两组中该位都可以有\(1\),或者都没有\(1\)。
  • 那么我们只需要贪心地插入二进制\(1\)的个数为偶数的那些位就行了,显然这样能使得最终答案最大。

下面口胡一下为什么不能直接用线性基来搞:

如果贪心地利用线性基直接求出一组答案,假设第\(i\)位二进制出现次数为奇数,那么我们可能就以\(i\)为基底,那么其余偶数位作为基底的"可能性"就降低了,所以我们在插入线性基的时候要避免奇数个数的位,这样能使答案最大。

  1. #include <bits/stdc++.h>
  2. #define fi first
  3. #define se second
  4. #define MP make_pair
  5. using namespace std;
  6. typedef long long ll;
  7. typedef pair<int, int> pii;
  8. const int N = 1e5 + 5;
  9. int n;
  10. ll a[N], p[62];
  11. bool chk[62];
  12. void insert(ll x) {
  13. for(int i = 60; i >= 0; i--) {
  14. if(chk[i]) continue;
  15. if(x >> i & 1) {
  16. if(!p[i]) {
  17. p[i] = x;
  18. break;
  19. }
  20. x ^= p[i];
  21. }
  22. }
  23. }
  24. int main() {
  25. ios::sync_with_stdio(false); cin.tie(0);
  26. cin >> n;
  27. ll all = 0;
  28. for(int i = 1; i <= n; i++) cin >> a[i], all ^= a[i];
  29. for(int i = 0; i <= 60; i++) {
  30. if(all >> i & 1) chk[i] = 1;
  31. }
  32. for(int i = 1; i <= n; i++) insert(a[i]);
  33. ll ans = 0;
  34. for(int i = 0; i <= 60; i++) {
  35. if(chk[i])
  36. for(int j = 0; j <= 60; j++) {
  37. if(p[j] >> i & 1) {
  38. p[j] ^= (1ll << i);
  39. }
  40. }
  41. }
  42. for(int i = 60; i >= 0; i--) {
  43. if((p[i] ^ ans) > ans) ans = p[i] ^ ans;
  44. }
  45. cout << ans + (ans ^ all);
  46. return 0;
  47. }

P.S:实现的话可以一开始就将\(a\)数组\(chk\)了的位的值减去,就让这些位不参与运算,写起来能更加简洁。

如下:

Code
  1. #include <bits/stdc++.h>
  2. #define fi first
  3. #define se second
  4. #define MP make_pair
  5. using namespace std;
  6. typedef long long ll;
  7. typedef pair<int, int> pii;
  8. const int N = 1e5 + 5;
  9. int n;
  10. ll a[N], p[62];
  11. void insert(ll x) {
  12. for(int i = 60; i >= 0; i--) {
  13. if(x >> i & 1) {
  14. if(!p[i]) {
  15. p[i] = x;
  16. break;
  17. }
  18. x ^= p[i];
  19. }
  20. }
  21. }
  22. int main() {
  23. ios::sync_with_stdio(false); cin.tie(0);
  24. cin >> n;
  25. ll all = 0;
  26. for(int i = 1; i <= n; i++) cin >> a[i], all ^= a[i];
  27. for(int i = 0; i <= 60; i++) {
  28. if(all >> i & 1) {
  29. for(int j = 1; j <= n; j++) {
  30. if(a[j] >> i & 1) a[j] -= (1ll << i);
  31. }
  32. }
  33. }
  34. for(int i = 1; i <= n; i++) insert(a[i]);
  35. ll ans = 0;
  36. for(int i = 60; i >= 0; i--) {
  37. if((p[i] ^ ans) > ans) ans = p[i] ^ ans;
  38. }
  39. cout << ans + (ans ^ all);
  40. return 0;
  41. }

AtCoder abc 141 F - Xor Sum 3(线性基)的更多相关文章

  1. Atcoder ABC 141

    Atcoder ABC 141 A - Weather Prediction SB题啊,不讲. #include<iostream> #include<cstdio> #inc ...

  2. CodeForces - 1101G :(Zero XOR Subset)-less(线性基)

    You are given an array a1,a2,…,an of integer numbers. Your task is to divide the array into the maxi ...

  3. [WC2011]最大XOR和路径 线性基

    [WC2011]最大XOR和路径 LG传送门 需要充分发掘经过路径的性质:首先注意不一定是简单路径,但由于统计的是异或值,重复走是不会被统计到的,考虑对于任意一条从\(1\)到\(n\)的路径的有效部 ...

  4. CF1101G (Zero XOR Subset)-less 线性基

    传送门 既然每一次选择出来的都是一个子段,不难想到前缀和计算(然而我没有想到--) 设异或前缀和为\(x_i\),假设我们选出来的子段为\([1,i_1],(i_1,i_2],...,(i_{k-1} ...

  5. 洛谷P4151 [WC2011] 最大XOR和路径 [线性基,DFS]

    题目传送门 最大XOR和路径 格式难调,题面就不放了. 分析: 一道需要深刻理解线性基的题目. 好久没打过线性基的题了,一开始看到这题还是有点蒙逼的,想了几种方法全被否定了.还是看了大佬的题解才会做的 ...

  6. [luogu4151 WC2011] 最大XOR和路径 (线性基)

    传送门 输入输出样例 输入样例#1: 5 7 1 2 2 1 3 2 2 4 1 2 5 1 4 5 3 5 3 4 4 3 2 输出样例#1: 6 说明 [样例说明] 根据异或的性质,将一个数异或两 ...

  7. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  8. 牛客练习赛26 D xor序列 (线性基)

    链接:https://ac.nowcoder.com/acm/contest/180/D 来源:牛客网 xor序列 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他 ...

  9. Wannafly Winter Camp 2020 Day 5J Xor on Figures - 线性基,bitset

    有一个\(2^k\cdot 2^k\) 的全零矩阵 \(M\),给出 \(2^k\cdot 2^k\) 的 \(01\) 矩阵 \(F\),现在可以将 \(F\) 的左上角置于 \(M\) 的任一位置 ...

随机推荐

  1. c# WF 第2节 窗体的添加与删除

    本节内容: 1: 窗体的添加 2: 窗体的删除 1: 窗体的添加 2: 窗体的删除 3:窗口的运行,发现只有一个form1 是因为

  2. monkey和monkeyrunner的区别

    简单来说: 1.monkey是在设备或模拟器直接运行adb shell命令生成随机事件来进行测试 2.monkeyrunner是通过API发送特定的命令和事件来控制设备 为了支持黑盒自动化测试的场景, ...

  3. lua 6 函数

    定义: function max(num1, num2) local result = 0 if (num1 > num2) then result = num1; else result = ...

  4. sql 以某个字段分组,另一个字段为参加比较的列,取得前n项的值

    假设表A有三个字段 { id int: subject varchar(20): socre int: } 语句为 select * from A  x where (select count(*) ...

  5. C# git忽略文件 (.gitignore )

    # Visual Studio # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific fi ...

  6. 题解 P3693 【琪露诺的冰雪小屋】

    知识点: 模拟 , 信仰 原题面 大 型 车 万 众 自 裁 现 场 分析题意: 操作: ICE_BARRAGE R C D S R:行 , C:列, D:方向 , S:强度 在(R,C) 向 D 射 ...

  7. UOJ Easy Round #5

    Preface 本着刷遍(只刷一遍)各大OJ的原则我找到了一场UOJ的比赛 无奈UOJ一般的比赛难度太大,我就精选了UER中最简单的一场打了一下,就当是CSP前的练习吧 A. [UER #5]万圣节的 ...

  8. Luogu P5022 旅行

    开始写复赛题了 先放张图纪念我惨烈的卡常之路 不说了,简直悲伤 题目链接 思路么..不想写了 Code //不要在意四十行超级加速,卡常用的 #include<bits/stdc++.h> ...

  9. leetcode 236. 二叉树的最近公共祖先LCA(后序遍历,回溯)

    LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百 ...

  10. 物联网架构成长之路(40)-Bladex开发框架入门

    0. 前言 前一小节,讲了如何入门,这里就简单讲一下如何自定义查询和权限控制配置. 1. 配置多租户 如果要启用该表的多租户功能,需要在application.yml 这里配置. 2. 配置模糊匹配 ...