ARC145E

题面

你有一个长度为 n 的序列 A ,你想通过小于等于 70000 次操作使 A 等于另一个序列 B ,或判断无解。

操作为:选择一个 k[1,n] ,对于 i[2,k],aiaiai1

数据范围 :n1000,ai<260

题解

首先分析一下操作,发现他是对 A 的一个前缀产生改变,即如果我们让 an=bn ,那么就可以不用管 n 了,所以我们可以考虑从后往前去让每一个 ai 满足。

现在我们考虑最终 ai 的值可以从哪里来。

因为操作是异或,所以如果设 S={a1,a2,...,ai1,ai} ,那么 ai 就是 S 的某一个子集 T 的异或和,并且 aiT

一定是子集吗?也就是所有情况都取得到吗?

考虑构造,设 01 序列 C ,其中 cj=1 表示在 T 中,我们从 1 遍历到 i ,然后保持 j 的值为 ajxTx<jax

  • cj+1=1,下一步操作就是 k=j+1 ,可以看出此时 aj+1 的值也是上面这一坨。
  • cj+1=0 ,下一步操作就是 k=j+2 ,此时 aj+2=aj+1ajaj+1 是上面的这一坨,之后从 aj+1 合并到 aj+2 的时候 aj+1 就会消掉。

所以可以证明所有子集都可以被构造出来。

那么怎么找到子集使 xTax=bi 呢?线性基!!!所以就做完了。

但是!这时候我们发现了一个严峻的问题:上面的构造是 O(n) 一次的,所以理论上最坏复杂度是 O(n2) 的,远远大于 70000 ,而且理论最小值也是 logain=60000 的,怎么会过呢?

但事实是就是能过,不知道是数据水还是有奇怪性质。

有没有复杂度保证的做法呢?

有!

我们发现正着做没法做,因为 ai 每次只会得到 ai1 的信息,理论上基本上都是要 O(n2) 的操作的。

这时候,上天(题解)告诉你要反着来,考虑对 B 操作。

首先看逆操作是什么:

A={a1,a2a1,a3a2,...,aiai1}=A={a1,a2,a3,...,ai}

那么 ai=j=1iaj 。(如果是 + ,那么 ai=j=1i(1)(ij)aj 。)

那么逆操作就是对于 i[2,k]aij=1iaj

这时候,我们发现,因为一次操作会给所有 2kbi 发生改变,这就意味着如果我们在构造的时候是可能改变前面的某个 基向量 的值的,这会有影响吗?

答案是没有!

基底的选取有着很高的自由度。具体地,

  • v1,v2,...,vi,...,vj,..vn线性无关,
  • v1,v2,...,vi+vj,...,vj,..vn也是线性无关的。
  • 也就是说,基向量相加减依然可以作为基向量。

—— from 王总课件。

那么如果我们考虑从前往后去构造线性基,那么当 i 作为基向量的时候, 让 bi 任意和 b1bi1 做异或运算, bi 永远都会是基向量,所以我们可以从前往后先扫一遍,这样我们就求出了一组基底。

现在考虑构造 bi ,最后一次操作肯定是 k=i ,让 bi=j=1ibj

考虑如何消除一个 bx ,发现我们只需要做一次 k=x+1 ,这样 bx+1 也有一个 bx ,所以 j=1ibj 里就没有 bx 了。

所以我们从后往前依次考虑每一个基向量 x ,如果判断 当前 j=1ibj 的值不能被 x 之前的基向量表示,那么就要按上面方法去除掉 bx

所以这样就是严格 nlogai 的复杂度。

启发

  • aiai1ai 的逆操作是 aij=1iaj
  • 基向量相加减依然可以作为基向量!

本文作者:qwq_123

本文链接:https://www.cnblogs.com/qwq-123/p/16542633.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   qwq_123  阅读(68)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起