FWT 学习笔记
和 都是在做加法卷积,从其形式 可以看出,其满足对应的下标 。
考虑把这个 换成位运算 来卷积。
即令这个符号为 ,有 。
考虑类似 的过程:
。
那能不能也这样通过 得到 ,然后得到 ,通过 得到 。
考虑构造系数 满足 。
那么根据 就有:
考虑卷积的形式,有 ,就有:
把两个最终的式子放在一起,就有 。
就能得到 。
又根据位运算每一位是独立的这一性质,考虑把 摊到 的每一位上。
即令 为 二进制下的第 高位( 为最高位),考虑得到了 ,有 。
只要有 ,那么就有 ,通过拆位证明。
如果知道了 ,又如何进行 呢?
考虑 ,那么对于最高位,在 时为 , 时为 。
令 分别为 舍弃最高位后的数,那就有 。
发现这也是可以分治的,考虑 为首位为 的 得到的序列, 同理。
那就有 。
再分讨一下 的值,就有 。
按照这个系数直接分治就行了。
因为只会往下分治 层,每一层都会重新计算 ,时间复杂度 。
考虑把 写为一个 的矩阵。
那么 只需要把 的 替换为其逆矩阵即 即可。
卷积:
需要满足 。
就有 。
可以构造出 。
卷积:
需要满足 。
就有 。
可以构造出 。
卷积:
需要满足 。
就有 。
可以构造出 。
模板题 Luogu P4717。
直接套用上面的做法即可。
可以直接从低位到高位递推减小常数。
此题 为位数,时间复杂度就为 。
#include<bits/stdc++.h>
using i64 = long long;
const i64 mod = 998244353, inv2 = (mod + 1) >> 1;
const int maxn = (1 << 17) + 2;
namespace FWT {
const i64 Bitor[2][2] = {{1, 1}, {1, 0}}, IBitor[2][2] = {{0, 1}, {1, mod - 1}};
const i64 Bitand[2][2] = {{1, 1}, {0, 1}}, IBitand[2][2] = {{1, mod - 1}, {0, 1}};
const i64 Bitxor[2][2] = {{1, 1}, {1, mod - 1}}, IBitxor[2][2] = {{inv2, inv2}, {inv2, mod - inv2}};
inline void FWT(i64 *a, const i64 B[2][2], int n) {
for (int i = 0; (1 << i) < n; i++)
for (int s = 0; s < n; s += 2 << i)
for (int p = s, ed = s + (1 << i); p < ed; p++) {
i64 x = a[p], y = a[p + (1 << i)];
a[p] = (B[0][0] * x + B[0][1] * y) % mod, a[p + (1 << i)] = (B[1][0] * x + B[1][1] * y) % mod;
}
}
};
i64 a[maxn], b[maxn], a_[maxn], b_[maxn];
int main() {
int n; scanf("%d", &n);
n = 1 << n;
for (int i = 0; i < n; i++) scanf("%lld", &a[i]);
for (int i = 0; i < n; i++) scanf("%lld", &b[i]);
auto solve = [&](int id) {
for (int i = 0; i < n; i++) a_[i] = a[i], b_[i] = b[i];
if (id == 1) FWT::FWT(a_, FWT::Bitor, n), FWT::FWT(b_, FWT::Bitor, n);
if (id == 2) FWT::FWT(a_, FWT::Bitand, n), FWT::FWT(b_, FWT::Bitand, n);
if (id == 3) FWT::FWT(a_, FWT::Bitxor, n), FWT::FWT(b_, FWT::Bitxor, n);
for (int i = 0; i < n; i++) (a_[i] *= b_[i]) %= mod;
if (id == 1) FWT::FWT(a_, FWT::IBitor, n);
if (id == 2) FWT::FWT(a_, FWT::IBitand, n);
if (id == 3) FWT::FWT(a_, FWT::IBitxor, n);
for (int i = 0; i < n; i++) printf("%lld ", a_[i]); printf("\n");
};
solve(1),solve(2), solve(3);
return 0;
}
本文作者:lhzawa
本文链接:https://www.cnblogs.com/lhzawa/p/18007392
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步