题目大意
给定两个下标均为[0..2n−1]的多项式A,B,数组C=A×B,满足
Ci=∑(j op k)=iAj∗Bk
其中op可以为三种位运算符号or,and,xor。
题解
这种问题有一个经典的做法,Fast Walsh-Hadamard Transform,但很难记忆,下面是种比较好推的做法。三种符号分类讨论。
Or
设当前A,B长度为2L,A=a+b∗xL,B=c+d∗xL,其实就是拆成两半。而且由于操作符是Or,所以可以直接通过∗xL实现左移L位。
那么
因为是Or,所以xL∗xL=xL,因此A∗B=ac+xL(bc+ad+bd)
那么我们可以先求出(a+b)∗(c+d)以及a∗c,然后用O(L)的时间就可以求出A∗B了。
时间复杂度T(L)=2∗T(L2)+O(L)=O(L∗logL)
Xor
设当前A,B长度为2L,A=a+b∗xL,B=c+d∗xL,其实就是拆成两半。而且由于操作符是Xor,所以可以直接通过∗xL实现左移L位。
那么
因为是Xor,所以xL∗xL=x0=1,因此A∗B=ac+xL(bc+ad)+bd
那么设X=(a+b)∗(c+d),Y=(a−b)∗(c−d),可以惊奇的发现bc+ad=X−Y2,ac+bd=X+Y2。于是一样用O(L)的时间就可以求出了。
时间复杂度T(L)=2∗T(L2)+O(L)=O(L∗logL)
And
一样把A,B分为两半,但现在不能用xL来左移了,因为是and。
但是可以发现的是,A∗B的左边只能由b∗d做出贡献,而且右边的贡献就是bc+ad+ac。
那么我们可以算出(a+b)∗(c+d),b∗d,然后拼接一下就好了。
时间复杂度T(L)=2∗T(L2)+O(L)=O(L∗logL)