Codeforces.472F.Design Tutorial: Change the Goal(构造 线性基 高斯消元)
\(Description\)
给定两个长为\(n\)的数组\(x_i,y_i\)。每次你可以选定\(i,j\),令\(x_i=x_i\ \mathbb{xor}\ x_j\)(\(i,j\)可以相等)。要求若干次操作后使得\(x\)变成\(y\),输出方案。操作次数不能多于\(10^6\),无解输出\(-1\)。
\(n\leq10^4,\ 0\leq x_i,y_i\leq10^9\)。
\(Solution\)
考虑异或的两个基本性质:
- 异或是可逆的,逆运算就是它本身。
- 可以交换两个数:
a^=b,b^=a,a^=b。
考虑线性基。构造出\(x\)的线性基,如果\(y\)中存在元素不能被\(x\)表示出来,那么无解。
我们发现对于不在线性基中的元素\(x_i\),得到\(y_i\)是很容易的,只需要求一下在线性基中\(\mathbb{xor}\)出\(y_i\)需要异或哪些数。
对于在线性基中的元素,设有\(t\)个,它们之间不是很好做。把\(t\)个\(x_i\)对应的\(y_i\)需要\(\mathbb{xor}\)哪些基写成一个\(t\)位二进制数。由第二个性质,我们可以高斯消元将这个\(t\times t\)的矩阵消成一个上三角矩阵,这样从高位到低位做不同基之间就互不影响了,我们可以\(\mathbb{xor}\)出这个矩阵。
而由第一个性质,将高斯消元的过程反过来操作这个上三角矩阵,就可以还原回\(y\)数组。
//46ms 3100KB
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define BIT 29
#define mp std::make_pair
#define pr std::pair<int,int>
#define gc() getchar()
typedef long long LL;
const int N=10005,M=BIT+2;
int x[N],y[N],base[M],is_base[N],b[M],sx[M],sy[N];
std::vector<pr> ans,opt;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
int main()
{
int n=read();
for(int i=1; i<=n; ++i) x[i]=read();
for(int i=1; i<=n; ++i) y[i]=read();
for(int i=1; i<=n; ++i)
{
is_base[i]=-1;
for(int j=BIT,s=0; ~j; --j)
if(x[i]>>j&1)
if(base[j]) x[i]^=x[base[j]], s^=sx[j];
else
{
is_base[i]=j, base[j]=i, sx[j]=s|(1<<j);
break;
}
}
int cnt=0;
for(int i=1; i<=n; ++i)
{
int s=0;
for(int j=BIT; ~j; --j)
if(y[i]>>j&1)
if(base[j]) y[i]^=x[base[j]], s^=sx[j];
else return puts("-1"),0;
if(~is_base[i]) {b[cnt]=i, sy[cnt++]=s; continue;}//可以等于0啊。。
ans.push_back(mp(i,i));
for(int j=BIT; ~j; --j) if(s>>j&1) ans.push_back(mp(i,base[j]));
}
for(int i=0; i<cnt; ++i)
{
int s=sy[i]; sy[i]=0;
for(int j=0; j<cnt; ++j) if(s>>is_base[b[j]]&1) sy[i]|=1<<j;
}
for(int i=0; i<cnt; ++i)
{
if(!(sy[i]>>i&1))
for(int j=i+1; j<cnt; ++j)
if(sy[j]>>i&1)
{
opt.push_back(mp(b[i],b[j]));
opt.push_back(mp(b[j],b[i]));
opt.push_back(mp(b[i],b[j]));
std::swap(sy[i],sy[j]);
break;
}
if(sy[i]>>i&1)
for(int j=i+1; j<cnt; ++j)
if(sy[j]>>i&1)
opt.push_back(mp(b[j],b[i])), sy[j]^=sy[i];
}
for(int i=0; i<cnt; ++i)
{
if(!(sy[i]>>i&1)) ans.push_back(mp(b[i],b[i]));
for(int j=i+1; j<cnt; ++j)
if(sy[i]>>j&1) ans.push_back(mp(b[i],b[j]));
}
std::reverse(opt.begin(),opt.end());
for(auto v:opt) ans.push_back(v);
printf("%d\n",ans.size());
for(auto v:ans) printf("%d %d\n",v.first,v.second);
return 0;
}
Codeforces.472F.Design Tutorial: Change the Goal(构造 线性基 高斯消元)的更多相关文章
- Educational Codeforces Round 63 (Rated for Div. 2) E 带模高斯消元
https://codeforces.com/contest/1155/problem/E 题意 \(f(x)=a_0+a_1x+a_2x^2+...+a_kx^k,k \leq 10,0 \leq ...
- Codeforces Gym10008E Harmonious Matrices(高斯消元)
[题目链接] http://codeforces.com/gym/100008/ [题目大意] 给出 一个n*m的矩阵,要求用0和1填满,使得每个位置和周围四格相加为偶数,要求1的数目尽量多. [题解 ...
- Codeforces 832E Vasya and Shifts - 高斯消元
题目传送门 快速的传送门I 快速的传送门II 题目大意 (题意比较复杂,请自行阅读原题) 可以将原题的字母都看成它们的在字符表中的下标,这样问题就变成给定$n$个$m$维向量$\vec{a_{1}}, ...
- Codeforces Round #114 (Div. 1) E. Wizards and Bets 高斯消元
E. Wizards and Bets 题目连接: http://www.codeforces.com/contest/167/problem/E Description In some countr ...
- CodeForces 24D Broken robot(期望+高斯消元)
CodeForces 24D Broken robot 大致题意:你有一个n行m列的矩形板,有一个机器人在开始在第i行第j列,它每一步会随机从可以选择的方案里任选一个(向下走一格,向左走一格,向右走一 ...
- Codeforces 1163E 高斯消元 + dfs
题意:给你一个集合,让你构造一个长度尽量长的排列,使得排列中任意相邻两个位置的数XOR后是集合中的数. 思路:我们考虑枚举i, 然后判断集合中所有小于1 << i的数是否可以构成一组异或空 ...
- Broken robot CodeForces - 24D (三对角矩阵简化高斯消元+概率dp)
题意: 有一个N行M列的矩阵,机器人最初位于第i行和第j列.然后,机器人可以在每一步都转到另一个单元.目的是转到最底部(第N个)行.机器人可以停留在当前单元格处,向左移动,向右移动或移动到当前位置下方 ...
- Codeforces 446D - DZY Loves Games(高斯消元+期望 DP+矩阵快速幂)
Codeforces 题目传送门 & 洛谷题目传送门 神仙题,%%% 首先考虑所有格子都是陷阱格的情况,那显然就是一个矩阵快速幂,具体来说,设 \(f_{i,j}\) 表示走了 \(i\) 步 ...
- Educational Codeforces Round 58 (Rated for Div. 2) G 线性基
https://codeforces.com/contest/1101/problem/G 题意 一个有n个数字的数组a[],将区间分成尽可能多段,使得段之间的相互组合异或和不等于零 题解 根据线性基 ...
随机推荐
- laravel 资源控制器
Artisan 生成器来生成一个资源控制器(在之前命名后加上 --resource 选项) php artisan make:controller PostController --resource ...
- java概念基础笔记整理
1.构造方法没有类型,有类型的不是不叫构造方法. 2.一个类的的成员变量可以是java允许的任何数据类型,一个类可以把某个对象作为自己的一个成员变量,如果用这样的类创建对象,那么该对象中就会其他对象, ...
- CSS3D写3d画廊滚动
CSS样式表 *{ margin: 0; padding: 0; } .wrapper{ width: 800px; height: 600px; background: #87CEEB; margi ...
- python面向对象三大特性之继承
继承是创建新类的方法,以下是几个概念 父类,基类,超类: 被继承的类 子类,派生类:继承而产出的类 单继承:继承一个父类 多继承:继承多个父类 继承: 什么是什么的关系 父类中没有的属性,在字类中出现 ...
- 437. 路径总和 III
方法一:48 ms /* sumUp递归子程序求解以root为根节点的子节点之和为sum的路径数目; pathSum递归部分是把根节点逐一考察,如以root->left,以root->ri ...
- C# 合并两张图片
private BitmapSource CombineImage(BitmapSource img1,BitmapSource img2) { var composeImg = new Render ...
- javascript OOP(上)(八)
一.OOP的概念和继承 1.OOP概念 面向对象程序设计(Object-oriented programming,OOP)是一种程序设计范型,同时也是一种程序开发的方法.对象指的是类的实例.它将对象作 ...
- java运算符-逻辑、三元运算符
1.逻辑运算符 逻辑运算符,它是用于布尔值进行运算的,运算的最终结果为布尔值true或false. 运算符 运算规则 范例 结果 & 与 false&true False | 或 fa ...
- bzoj 4621: Tc605 动态规划
题解: 一道比较简单的题目 想着想着就把题目记错了..想成了可以把某段区间覆盖为其中一个数 其实是比较简单的 每个点的贡献一定是一个区间(就跟zjoi2018那题一样) 然后问题就变成了给你n个区间让 ...
- 1900型USB接口扫描枪设置虚拟串口模式提升扫描速度
在使用扫描枪的过程中,发现扫描二维码速度比较慢,不到100个字符,花了大概2-3秒的时间才完成显示,这个速度不能忍受啊.通过度娘,说是可以将USB键盘模式接收字符转换成虚拟串口接收,这样可以大大提高速 ...