定义 i i i和 j j j之间的奇偶性为 ( i & j ) (i\&j) (i&j)中为1的位数的奇偶性,若为偶数则奇偶性是0,若为奇数则奇偶性是1。记作 d ( i , j ) d(i,j) d(i,j)
令 F W T [ V ] i = ∑ d ( i , j ) = 0 V j − ∑ d ( i , j ) = 1 V j \large FWT[V]_i=\sum_{d(i,j)=0}V_j-\sum_{d(i,j)=1}V_j FWT[V]i=∑d(i,j)=0Vj−∑d(i,j)=1Vj
就有了 F W T [ C ] i = F W T [ A ] i ∗ F W T [ B ] i \large FWT[C]_i=FWT[A]_i*FWT[B]_i FWT[C]i=FWT[A]i∗FWT[B]i
看看怎么分治,此处 X X X与 Y Y Y的实际含义为 { X i = ∑ d ( i , j ) = 0 , j 在 左 边 V j − ∑ d ( i , j ) = 1 , j 在 左 边 V j Y i = ∑ d ( i , j ) = 0 , j 在 右 边 V j − ∑ d ( i , j ) = 1 , j 在 右 边 V j \Large \left\{ \begin{aligned} X_i=&\sum_{d(i,j)=0,j在左边}V_j-\sum_{d(i,j)=1,j在左边}V_j\\ Y_i=&\sum_{d(i,j)=0,j在右边}V_j-\sum_{d(i,j)=1,j在右边}V_j\\ \end{aligned} \right. ⎩⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎧Xi=Yi=d(i,j)=0,j在左边∑Vj−d(i,j)=1,j在左边∑Vjd(i,j)=0,j在右边∑Vj−d(i,j)=1,j在右边∑Vj
有 { A n s i = X i + Y i . . . . . . . . . . . . . . . . . ( 1 ) A n s i + l e n / 2 = X i − Y i . . . . . . . . . ( 2 ) \Large \left\{ \begin{aligned} &Ans_i=X_i+Y_i.................(1)\\ &Ans_{i+len/2}=X_i-Y_i.........(2)\\ \end{aligned} \right. ⎩⎪⎨⎪⎧Ansi=Xi+Yi.................(1)Ansi+len/2=Xi−Yi.........(2)
怎么想呢,分类讨论吧。由于:
逆变换可自行推导(或看下方代码)
写法跟FFT,NTT一模一样,还要更简(hao)单(bei)
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 1<<17;
const int mod = 998244353;
const int inv2 = 499122177;
int n, a[MAXN], b[MAXN];
int a1[MAXN], a2[MAXN];
inline void FWT_or(int arr[], const int& len, const int& flg)
{
register int x, y;
for(register int i = 2; i <= len; i<<=1)
for(register int j = 0; j < len; j += i)
for(register int k = j; k < j + i/2; ++k)
{
x = arr[k], y = arr[k + i/2];
if(~flg) arr[k + i/2] = (x + y) % mod;
else arr[k + i/2] = (y - x + mod) % mod;
}
}
inline void FWT_and(int arr[], const int& len, const int& flg)
{
register int x, y;
for(register int i = 2; i <= len; i<<=1)
for(register int j = 0; j < len; j += i)
for(register int k = j; k < j + i/2; ++k)
{
x = arr[k], y = arr[k + i/2];
if(~flg) arr[k] = (x + y) % mod;
else arr[k] = (x - y + mod) % mod;
}
}
inline void FWT_xor(int arr[], const int& len, const int& flg)
{
register int x, y;
for(register int i = 2; i <= len; i<<=1)
for(register int j = 0; j < len; j += i)
for(register int k = j; k < j + i/2; ++k)
{
x = arr[k], y = arr[k + i/2];
if(~flg) arr[k] = (x + y) % mod, arr[k + i/2] = (x - y + mod) % mod;
else arr[k] = (LL)(x + y) * inv2 % mod, arr[k + i/2] = (LL)(x - y + mod) * inv2 % mod;
}
}
inline void solve_or(const int& len)
{
memcpy(a1, a, sizeof a);
memcpy(a2, b, sizeof b);
FWT_or(a1, len, 1);
FWT_or(a2, len, 1);
for(int i = 0; i < len; ++i)
a2[i] = (LL)a1[i] * a2[i] % mod;
FWT_or(a2, len, -1);
for(int i = 0; i < len; ++i)
printf("%d%c", a2[i], i == len-1 ? '\n' : ' ');
}
inline void solve_and(const int& len)
{
memcpy(a1, a, sizeof a);
memcpy(a2, b, sizeof b);
FWT_and(a1, len, 1);
FWT_and(a2, len, 1);
for(int i = 0; i < len; ++i)
a2[i] = (LL)a1[i] * a2[i] % mod;
FWT_and(a2, len, -1);
for(int i = 0; i < len; ++i)
printf("%d%c", a2[i], i == len-1 ? '\n' : ' ');
}
inline void solve_xor(const int& len)
{
memcpy(a1, a, sizeof a);
memcpy(a2, b, sizeof b);
FWT_xor(a1, len, 1);
FWT_xor(a2, len, 1);
for(int i = 0; i < len; ++i)
a2[i] = (LL)a1[i] * a2[i] % mod;
FWT_xor(a2, len, -1);
for(int i = 0; i < len; ++i)
printf("%d%c", a2[i], i == len-1 ? '\n' : ' ');
}
int main ()
{
scanf("%d", &n); n = 1<<n;
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
for(int i = 0; i < n; ++i) scanf("%d", &b[i]);
solve_or(n);
solve_and(n);
solve_xor(n);
}