FWT模板

来源:互联网 发布:键盘钢琴软件 编辑:程序博客网 时间:2024/05/19 05:29

FWT

ci=jk=iaj×bk=kj[jk=i]aj×bk
 ({,,}, i,j,k{0,...,2n1})

FWT可以用于解决上述的式子,其中 可以为二进制的逻辑运算如:异或、与、或、非与…

以异或为例:

给定两个数集 AB,满足 2n=|A|=|B|,不足用 0 补,求数集 C,其中 ci=jk=iaj×bkci 表示 C 中的第 i 个数,下标从 02n1)。

这个算式可以直接模拟,O(4n),不优秀。

假设可以将数集 AB 通过某种变换变为 AB,得到 C,其中 ci=ai×bi,再将 C 某种逆变换,得到 C,问题就可以得到解决了。

于是突然发现了这样的一种变换

举个例子,|A|=|B|=4(下标用二进制表示)

c00=a00×b00+a01×b01+a10×b10+a11×b11

c01=a00×b01+a01×b00+a10×b11+a11×b10

c10=a00×b10+a01×b11+a10×b00+a11×b01

c11=a00×b11+a01×b10+a10×b01+a11×b00

有点丧呀,做法都懂,概念还需研究


FWT模板,包含or和xor

#include <cstdio>#include <cstring>#define R registerconst int Mod = 998244353, p = 2341;int a[1 << 20], b[1 << 20], c[1 << 20];void FWTor(R int *A, R int l, R int r){    if(r - l <= 1) return ;    R int mid = l + r >> 1;    FWTor(A, l, mid), FWTor(A, mid, r);    for(R int i = l, j = mid; j < r; i++, j++) (A[j] += A[i]) %= Mod;}void unFWTor(R int *A, R int l, R int r){    if(r - l <= 1) return ;    R int mid = l + r >> 1;    unFWTor(A, l, mid), unFWTor(A, mid, r);    for(R int i = l, j = mid; j < r; i++, j++) (A[j] -= A[i] - Mod) %= Mod;}void FWTxor(R int *A, R int l, R int r){    if(r - l <= 1) return ;    R int mid = l + r >> 1;    FWTxor(A, l, mid), FWTxor(A, mid, r);    for(R int i = l, j = mid; j < r; i++, j++)     {        R int f = A[i], g = A[j];        A[i] = (f + g) % Mod, A[j] = (f - g) % Mod;    }}void unFWTxor(R int *A, R int l, R int r){    if(r - l <= 1) return ;    R int mid = l + r >> 1;    unFWTxor(A, l, mid), unFWTxor(A, mid, r);    for(R int i = l, j = mid; j < r; i++, j++)     {        R int f = A[i], g = A[j];        A[i] = 1ll * (f + g)  * 499122177 % Mod, A[j] = 1ll * (f - g)  * 499122177 % Mod;    }}int main(){    R int n;    scanf("%d", &n);    for(R int i = 0; i < (1 << n); i++) scanf("%d", &a[i]);    for(R int i = 0; i < (1 << n); i++) scanf("%d", &b[i]);    R int t; scanf("%d", &t);    if(t == 1)    {        FWTor(a, 0, 1 << n);        FWTor(b, 0, 1 << n);        for(R int i = 0; i < (1 << n); i++) c[i] = 1ll * a[i] * b[i] % Mod;        unFWTor(c, 0, 1 << n);      }    else    {        FWTxor(a, 0, 1 << n);        FWTxor(b, 0, 1 << n);        for(R int i = 0; i < (1 << n); i++) c[i] = 1ll * a[i] * b[i] % Mod;        unFWTxor(c, 0, 1 << n);      }    for(R int i = 0; i < (1 << n); i++) printf("%d ", c[i]); puts("");    R int Ans = 0;    for(R int i = 0; i < (1 << n); i++) Ans = (1ll * Ans * p + c[i]) % Mod;    printf("%d", Ans);    return 0;}
原创粉丝点击