Codeforces 251D - Two Sets(异或方程组)
题意:
你有一个可重集 \(S=\{a_1,a_2,\dots,a_n\}\),你要把它划分成两个可重集 \(S_1,S_2\) 使得 \(S\) 中每个元素都恰好属于 \(S_1\) 与 \(S_2\) 之一。
记 \(X_1\) 为 \(S_1\) 中所有元素的异或和,\(X_2\) 为 \(S_2\) 中所有元素的异或和。
最大化 \(X_1+X_2\),如果有多种分配方案,再最小化 \(X_1\)。
\(n \in [1,10^5],a_i \in [1,10^{18}]\)
暑假省选班讲过这道题,当时听得一脸懵B,还问lxr为什么线性基本质上就是高斯消元。。。。。。wtclwtcl
设 \(X=a_1 \oplus a_2 \oplus a_3 \oplus\dots\oplus a_n\),那么显然有 \(X_1\oplus X_2=X\)。
考虑 \(X\) 二进制上的每一位,如果 \(X\) 的第 \(i\) 位为 \(1\),那么意味着它只能拆成 \(0\) 和 \(1\),不会对 \(X_1+X_2\) 产生影响。
但如果 \(X\) 的第 \(i\) 位为 \(0\),那么它可以拆成 \(0,0\) 或者 \(1,1\),我们的目标是让 \(X_1+X_2\) 尽可能大,我们就要尽量选择 \(1,1\),也就是要尽量让 \(X_1\) 的第 \(i\) 位为 \(1\)。
我们假设 \(n\) 个未知数 \(x_1,x_2,\dots,x_n\),\(x_i=1\) 表示 \(i\) 被分配到第一堆,\(x_i=0\) 表示 \(i\) 被分配到第二堆。
那么 \(X_1\) 的第 \(b\) 位为 \(1\) 等价于一个异或方程 \(t_1x_1\oplus t_2x_2\oplus\dots\oplus t_nx_n=1\),其中 \(t_i\) 表示 \(a_i\) 二进制下的第 \(b\) 位是否为 \(1\)。
具体地来说,我们找到 \(X\) 中最高的为 \(0\) 的二进制位 \(b\),根据之前的推论可以列出一个异或方程,如果该异或方程有解,那么我们肯定要在这一位上放 \(1\)。因为如果你在这一位上放 \(1\),哪怕后面都是 \(0\),那 \(X_1+X_2\) 也有 \(2^{b+1}\),而如果你在这一位上放 \(0\),哪怕后面都放 \(1\),结果也只有 \(2^{b+1}-2\)。
我们考虑这样的贪心做法:从高位向低位枚举每一个 \(X\) 二进制下为 \(0\) 的二进制位 \(b\),我们尝试着在这一位上放 \(1\),如果存在一种方案,它既能够满足前面的条件(在第 \(b\) 位前面放 \(1\) 的位都对应一个异或方程,把它们联立起来得到的异或方程组),那么我们就在这一位上放 \(1\),否则就在这一位上放 \(0\)。
最大化 \(X_1+X_2\) 之后,我们再考虑 \(X_1\) 尽量小这个条件。这时候 \(X\) 为 \(1\) 的二进制位就要派上用场了。对于 \(X\) 二进制下为 \(1\) 的位,它又可以细分为第 \(1\) 堆分配 \(0\),第 \(2\) 堆分配 \(1\),以及第 \(1\) 堆分配 \(1\),第 \(2\) 堆分配 \(0\)。我们肯定希望第一堆分配地尽可能少,于是我们重复一遍前面的操作,找到一个 \(1\) 位就尝试填 \(0\),就可以了。
于是我们有了优秀的 \(n \log^3a_i\) 的做法,每次就联立出一个异或方程组,然后高斯消元判断这个异或方程组是否有解。
但其实并不用每次都重新消一遍,对于每个新的异或方程,都用前面的方程消去它的最高位(类似于线性基?)。这样是 \(n\log^2a_i\) 的,再注意到每一位系数都是 \(0/1\),可以用 bitset
再搞掉一个 \(\log\)。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
const int MAXN=1e5+5;
const int MAXB=63+2;
int n;ll a[MAXN],s=0;
bitset<MAXN> bt[MAXB];
int hi[MAXN],pos[MAXN],cur=0,ans[MAXN];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s^=a[i];
for(int i=62;~i;i--) if(!(s>>i&1)){
++cur;
for(int j=1;j<=n;j++) if((a[j]>>i)&1) bt[cur][j]=1;
bt[cur][n+1]=1;
for(int j=1;j<cur;j++) if(bt[cur][hi[j]]) bt[cur]^=bt[j];
for(int j=1;j<=n;j++) if(bt[cur][j]){hi[cur]=j;break;}
if(!hi[cur]){bt[cur].reset();cur--;continue;}
for(int j=1;j<cur;j++){
if(bt[j][hi[cur]]) bt[j]^=bt[cur];
}
}
for(int i=62;~i;i--) if(s>>i&1){
++cur;
for(int j=1;j<=n;j++) if((a[j]>>i)&1) bt[cur][j]=1;
bt[cur][n+1]=0;
for(int j=1;j<cur;j++) if(bt[cur][hi[j]]) bt[cur]^=bt[j];
for(int j=1;j<=n;j++) if(bt[cur][j]){hi[cur]=j;break;}
if(!hi[cur]){bt[cur].reset();cur--;continue;}
for(int j=1;j<cur;j++){
if(bt[j][hi[cur]]) bt[j]^=bt[cur];
}
}
for(int i=1;i<=cur;i++) ans[hi[i]]=bt[i][n+1];
for(int i=1;i<=n;i++) printf("%d ",2-ans[i]);
return 0;
}
Codeforces 251D - Two Sets(异或方程组)的更多相关文章
- 【HDU 5833】Zhu and 772002(异或方程组高斯消元)
300个最大质因数小于2000的数,选若干个它们的乘积为完全平方数有多少种方案. 合法方案的每个数的质因数的个数的奇偶值异或起来为0. 比如12=2^2*3,对应的奇偶值为01(2的个数是偶数为0,3 ...
- 小游戏 Lights Out (关灯) 的求解 —— 异或方程组
Author : Evensgn Blog Link : http://www.cnblogs.com/JoeFan/ Article Link : http://www.cnblogs.com/J ...
- hdu 5833 Zhu and 772002 异或方程组高斯消元
ccpc网赛卡住的一道题 蓝书上的原题 但是当时没看过蓝书 今天又找出来看看 其实也不是特别懂 但比以前是了解了一点了 主要还是要想到构造异或方程组 异或方程组的消元只需要xor就好搞了 数学真的是硬 ...
- bzoj千题计划187:bzoj1770: [Usaco2009 Nov]lights 燈 (高斯消元解异或方程组+枚举自由元)
http://www.lydsy.com/JudgeOnline/problem.php?id=1770 a[i][j] 表示i对j有影响 高斯消元解异或方程组 然后dfs枚举自由元确定最优解 #in ...
- bzoj千题计划105:bzoj3503: [Cqoi2014]和谐矩阵(高斯消元法解异或方程组)
http://www.lydsy.com/JudgeOnline/problem.php?id=3503 b[i][j] 表示i对j是否有影响 高斯消元解异或方程组 bitset优化 #include ...
- BZOJ.1923.[SDOI2010]外星千足虫(高斯消元 异或方程组 bitset)
题目链接 m个方程,n个未知量,求解异或方程组. 复杂度比较高,需要借助bitset压位. 感觉自己以前写的(异或)高斯消元是假的..而且黄学长的写法都不需要回代. //1100kb 324ms #i ...
- bzoj 2466 异或方程组
对于每个灯,我们用一个变量表示其决策,xu=0表示不选,xu=1表示选.因为每个灯最后必须都亮,所以每个等都对应一个异或方程. 解这个异或方程组,有几种情况: 1.存在唯一解(得到的上三角系数矩阵的主 ...
- 【BZOJ】2466: [中山市选2009]树 高斯消元解异或方程组
[题意]给定一棵树的灯,按一次x改变与x距离<=1的点的状态,求全0到全1的最少次数.n<=100. [算法]高斯消元解异或方程组 [题解]设f[i]=0/1表示是否按第i个点的按钮,根据 ...
- 高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯
高斯消元求解异或方程组: 比较不错的一篇文章:http://blog.sina.com.cn/s/blog_51cea4040100g7hl.html cojs.tk 539. 牛棚的灯 ★★☆ ...
随机推荐
- 指标统计:基于流计算 Oceanus(Flink) 实现实时 UVPV 统计
作者:吴云涛,腾讯 CSIG 高级工程师导语 | 最近梳理了一下如何用 Flink 来实现实时的 UV.PV 指标的统计,并和公司内微视部门的同事交流.然后针对该场景做了简化,并发现使用 Flink ...
- 正则表达式: NFA引擎匹配原理
NFA引擎匹配原理 1 为什么要了解引擎匹配原理 一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动 ...
- 设置nginx进程可打开最大的文件数
涉及到的nginx配置参数: worker_processes: 表示操作系统启动多少个工作进程在运行,一般这个参数设置成CPU核数的倍数 worker_connections:表示nginx的工作进 ...
- [HNOI2009]双递增序列(洛谷P4728)+小烈送菜(内部训练题)——奇妙的dp
博主学习本题的经过嘤嘤嘤: 7.22 : 听学长讲(一知半解)--自己推(推不出来)--网上看题解--以为自己会了(网上题解是错的)--发现错误以后又自己推(没推出来)--给学长发邮件--得到正确解法 ...
- 洛谷 P3195 [HNOI2008] 玩具装箱
链接: P3195 题意: 给出 \(n\) 个物品及其权值 \(c\),连续的物品可以放进一个容器,如果将 \(i\sim j\) 的物品放进一个容器,产生的费用是 \(\left(j-i+\sum ...
- DDD领域驱动设计架构模式:防腐层(Anti-corruption layer)
在微服务(Microservices)架构实践中,架构设计借用了DDD中的一些概念和技术,比如一个微服务对应DDD中的一个限界上下文(Bounded Context):在微服务设计中应该首先识别出DD ...
- 连续子序列的最大和 牛客网 剑指Offer
连续子序列的最大和 牛客网 剑指Offer 题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量 ...
- Netfilter和iptables介绍
前言 在开始Kubernetes的网络之前我们先来学习Netfilter,Netfilter可能了解的人比较少,但是iptables用过 Linux的都应该知道.本文主要介绍Netfilter与ipt ...
- 远程设备管理opendx平台搭建-server,agent以及front实际搭建
本系列文章讲述的是一个系列的第二部分,最终可以搭建一整套设备远程管理平台,与stf不同的是,opendx搭建较为简单,而且由于底层是appium来支持的,所以,较容易支持ios,也容易支持更高版本的安 ...
- 几个简单的文本处理工具:diff,patch,grep,cut,sort,tr
1:文本处理工具: 1:diff and patch : diff是比较文件或者目录的不同,主要有3个用法: diff file1 file2 :比较file1和file2的不同:diff -u ...