ARC145E
作者:互联网
题面
你有一个长度为 \(n\) 的序列 \(A\) ,你想通过小于等于 \(70000\) 次操作使 \(A\) 等于另一个序列 \(B\) ,或判断无解。
操作为:选择一个 \(k\in[1,n]\) ,对于 \(i\in[2,k],a_i\leftarrow a_i\oplus a_{i-1}\) 。
数据范围 :\(n\le 1000,a_i< 2^{60}\) 。
题解
首先分析一下操作,发现他是对 \(A\) 的一个前缀产生改变,即如果我们让 \(a_n=b_n\) ,那么就可以不用管 \(n\) 了,所以我们可以考虑从后往前去让每一个 \(a_i\) 满足。
现在我们考虑最终 \(a_i\) 的值可以从哪里来。
因为操作是异或,所以如果设 \(S=\{a_1,a_2,..., a_{i-1},a_i\}\) ,那么 \(a_i\) 就是 \(S\) 的某一个子集 \(T\) 的异或和,并且 \(a_i\in T\) 。
一定是子集吗?也就是所有情况都取得到吗?
考虑构造,设 \(01\) 序列 \(C\) ,其中 \(c_j=1\) 表示在 \(T\) 中,我们从 \(1\) 遍历到 \(i\) ,然后保持 \(j\) 的值为 \(a_j\oplus_{x\in T\and x<j} a_x\) 。
- 若 \(c_{j+1}=1\),下一步操作就是 \(k={j+1}\) ,可以看出此时 \(a_{j+1}\) 的值也是上面这一坨。
- 若 \(c_{j+1}=0\) ,下一步操作就是 \(k={j+2}\) ,此时 \(a_{j+2}=a_{j+1}\oplus a_{j}\) 而 \(a_{j+1}\) 是上面的这一坨,之后从 \(a_{j+1}\) 合并到 \(a_{j+2}\) 的时候 \(a_{j+1}\) 就会消掉。
所以可以证明所有子集都可以被构造出来。
那么怎么找到子集使 \(\oplus_{x\in T} a_x=b_i\) 呢?线性基!!!所以就做完了。
但是!这时候我们发现了一个严峻的问题:上面的构造是 \(O(n)\) 一次的,所以理论上最坏复杂度是 \(O(n^2)\) 的,远远大于 \(70000\) ,而且理论最小值也是 \(\log a_i n=60000\) 的,怎么会过呢?
但事实是就是能过,不知道是数据水还是有奇怪性质。
有没有复杂度保证的做法呢?
有!
我们发现正着做没法做,因为 \(a_i\) 每次只会得到 \(a_{i-1}\) 的信息,理论上基本上都是要 \(O(n^2)\) 的操作的。
这时候,上天(题解)告诉你要反着来,考虑对 \(B\) 操作。
首先看逆操作是什么:
\[A=\{a_1,a_2\oplus a_1,a_3\oplus a_2,...,a_i\oplus a_{i-1}\}=A'=\{a'_1,a'_2,a'_3,...,a'_i\} \]那么 \(a'_i=\oplus_{j=1}^i a_{j}\) 。(如果是 \(+\) ,那么 \(a_i'=\sum_{j=1}^i (-1)^{(i-j)} a_j\) 。)
那么逆操作就是对于 \(i\in[2,k]\),\(a_i\leftarrow \oplus_{j=1}^i a_{j}\)
这时候,我们发现,因为一次操作会给所有 \(2\sim k\) 的 \(b_i\) 发生改变,这就意味着如果我们在构造的时候是可能改变前面的某个 基向量 的值的,这会有影响吗?
答案是没有!
基底的选取有着很高的自由度。具体地,
- 若\(\vec{v_1},\vec{v_2},...,\vec{v_i},...,\vec{v_j},..\vec{v_n}\)线性无关,
- 则\(\vec{v_1},\vec{v_2},...,\vec{v_i}+\vec{v_j},...,\vec{v_j},..\vec{v_n}\)也是线性无关的。
- 也就是说,基向量相加减依然可以作为基向量。
—— from 王总课件。
那么如果我们考虑从前往后去构造线性基,那么当 \(i\) 作为基向量的时候, 让 \(b_i\) 任意和 \(b_1\sim b_{i-1}\) 做异或运算, \(b_i\) 永远都会是基向量,所以我们可以从前往后先扫一遍,这样我们就求出了一组基底。
现在考虑构造 \(b_i\) ,最后一次操作肯定是 \(k=i\) ,让 \(b_i=\oplus_{j=1}^i b_{j}\) 。
考虑如何消除一个 \(b_x\) ,发现我们只需要做一次 \(k=x+1\) ,这样 \(b_{x+1}\) 也有一个 \(b_x\) ,所以 \(\oplus_{j=1}^i b_{j}\) 里就没有 \(b_x\) 了。
所以我们从后往前依次考虑每一个基向量 \(x\) ,如果判断 当前 \(\oplus_{j=1}^i b_{j}\) 的值不能被 \(x\) 之前的基向量表示,那么就要按上面方法去除掉 \(b_x\) 。
所以这样就是严格 \(n\log a_i\) 的复杂度。
启发
- \(a_i\leftarrow a_{i-1}\oplus a_i\) 的逆操作是 \(a_i\leftarrow \oplus_{j=1}^i a_{j}\) 。
- 基向量相加减依然可以作为基向量!
标签:...,leftarrow,ARC145E,vec,操作,oplus,向量 来源: https://www.cnblogs.com/qwq-123/p/16542633.html