题目大意
给定两个下标均为
[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)