00:00:00
FWT 笔记
用于给定
的问题。其中
0. 核心思想
构造多项式
1. 按位或
构造
则
考虑如何将
除最高位外,左边的第
按层自下向上递推,不断增加对右侧贡献的间隔长度即可。
考虑将
点击查看代码
cpp
// 当前分治区间长度为 p,左端点为 i,半个区间的长度为 q
// 左边第 j 个数向右边第 j 个数贡献(i+j -> i+j+p)
void OR(int *f, int opt) {
for (int p = 2, q = 1; p <= 1 << n; p <<= 1, q <<= 1)
for (int i = 0; i < 1 << n; i += p)
for (int j = 0; j < q; j++)
f[i + j + q] = (f[i + j + q] + f[i + j] * opt + mod) % mod;
}2. 按位与
和按位或同理,只是变成右边向左边贡献了。
点击查看代码
cpp
void AND(int *f, int opt) {
for (int p = 2, q = 1; p <= 1 << n; p <<= 1, q <<= 1)
for (int i = 0; i < 1 << n; i += p)
for (int j = 0; j < q; j++)
f[i + j] = (f[i + j] + f[i + j + q] * opt + mod) % mod;
}3. 按位异或
构造
其中
可以发现
后面那个
令
因此
考虑
首先考虑这个
接着考虑右边,因为全都多了一位,所以他们内部之间的
由于只关心
综上,
考虑从
点击查看代码
cpp
void XOR(int *f, int opt) {
for (int p = 2, q = 1; p <= 1 << n; p <<= 1, q <<= 1)
for (int i = 0; i < 1 << n; i += p)
for (int j = 0; j < q; j++) {
int l = f[i + j], r = f[i + j + q];
f[i + j] = (l + r) % mod * opt % mod;
f[i + j + q] = (l - r + mod) % mod * opt % mod;
}
}