xht
2019-12-11 03:10:04
记对序列
已知序列
若
那么我们可以利用上述过程
在 OI 中,FWT 是用于解决对下标进行位运算卷积问题的方法。
其中
要求
显然有
构造
则有
要求
令
则有
其中
于是可以分治。
inline void OR(modint *f) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j+k] += f[i+j];
}
由
可得
inline void IOR(modint *f) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j+k] -= f[i+j];
}
显然两份代码可以合并。
inline void OR(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j+k] += f[i+j] * x;
}
同理或。
inline void AND(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k] * x;
}
定义
满足
构造
则有
因此
inline void XOR(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k],
f[i+j+k] = f[i+j] - f[i+j+k] - f[i+j+k],
f[i+j] *= x, f[i+j+k] *= x;
}
const int N = 1 << 17 | 1;
int n, m;
modint A[N], B[N], a[N], b[N];
inline void in() {
for (int i = 0; i < n; i++) a[i] = A[i], b[i] = B[i];
}
inline void get() {
for (int i = 0; i < n; i++) a[i] *= b[i];
}
inline void out() {
for (int i = 0; i < n; i++) print(a[i], " \n"[i==n-1]);
}
inline void OR(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j+k] += f[i+j] * x;
}
inline void AND(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k] * x;
}
inline void XOR(modint *f, modint x = 1) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j++)
f[i+j] += f[i+j+k],
f[i+j+k] = f[i+j] - f[i+j+k] - f[i+j+k],
f[i+j] *= x, f[i+j+k] *= x;
}
int main() {
rd(m), n = 1 << m;
for (int i = 0; i < n; i++) rd(A[i]);
for (int i = 0; i < n; i++) rd(B[i]);
in(), OR(a), OR(b), get(), OR(a, P - 1), out();
in(), AND(a), AND(b), get(), AND(a, P - 1), out();
in(), XOR(a), XOR(b), get(), XOR(a, (modint)1 / 2), out();
return 0;
}