(1) 计算 c i = ∑ i = j ∣ k a j b k c_i=\sum_{i=j|k} a_jb_k ci=∑i=j∣kajbk
设 f w t [ a ] i = ∑ j ∣ i = i a j fwt[a]_i=\sum_{j|i=i} a_j fwt[a]i=∑j∣i=iaj,设序列左半边为 a 0 a_0 a0,右半边为 a 1 a_1 a1,可以得到:
f w t [ a ] = m e r g e r ( f w t [ a 0 ] , f w t [ a 0 ] + f w t [ a 1 ] ) fwt[a]=merger(fwt[a_0],fwt[a_0]+fwt[a_1]) fwt[a]=merger(fwt[a0],fwt[a0]+fwt[a1])
即,取 i = 0 i = 0 i=0 时, j = 0 j =0 j=0,满足 j ∣ i = i j | i = i j∣i=i 。取 i = 1 i = 1 i=1 时, j = 0 j =0 j=0 或者 1 1 1
那么从 f w t [ a ] fwt[a] fwt[a] 变为 a a a 就相当于求逆
a = m e r g e r ( a 0 , a 1 − a 0 ) a=merger(a_0,a_1-a_0) a=merger(a0,a1−a0)
(2) 计算 c i = ∑ i = j & k a j b k c_i=\sum_{i=j\&k} a_jb_k ci=∑i=j&kajbk
设 f w t [ a ] i = ∑ j & i = i a j fwt[a]_i=\sum_{j\&i=i} a_j fwt[a]i=∑j&i=iaj,设序列左半边为 a 0 a_0 a0,右半边为 a 1 a_1 a1,可以得到:
f w t [ a ] = m e r g e r ( f w t [ a 0 ] + f w t [ a 1 ] , f w t [ a 1 ] ) fwt[a]=merger(fwt[a_0]+fwt[a_1],fwt[a_1]) fwt[a]=merger(fwt[a0]+fwt[a1],fwt[a1])
即,取 i = 0 i = 0 i=0 时, j = 0 j =0 j=0 或者 1 1 1,满足 j & i = i j \& i = i j&i=i 。取 i = 1 i = 1 i=1 时, j = 0 j =0 j=0
那么从 f w t [ a ] fwt[a] fwt[a] 变为 a a a 就相当于求逆
a = m e r g e r ( a 0 − a 1 , a 1 ) a=merger(a_0-a_1,a_1) a=merger(a0−a1,a1)
(3) 计算 c i = ∑ i = j ⊕ k a j b k c_i=\sum_{i=j \oplus k} a_jb_k ci=∑i=j⊕kajbk
f w t [ a ] = m e r g e r ( f w t [ a 0 ] + f w t [ a 1 ] , f w t [ a 0 ] − f w t [ a 1 ] ) fwt[a]=merger(fwt[a_0]+fwt[a_1],fwt[a_0]-fwt[a_1]) fwt[a]=merger(fwt[a0]+fwt[a1],fwt[a0]−fwt[a1])
a = m e r g e r ( a 0 + a 1 2 , a 0 − a 1 2 ) a=merger(\frac {a_0+a_1}2,\frac {a_0-a_1}2) a=merger(2a0+a1,2a0−a1)
参考链接
习题:https://www.luogu.com.cn/problem/CF662C
链接:https://www.luogu.com.cn/problem/P4717
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=150000,mod=998244353,inv2=499122177;
int n,total;
int a[maxn],b[maxn],A[maxn],B[maxn];
void add(int &x,int y)
{
x+=y;
if(x>=mod) x-=mod;
if(x<0) x+=mod;
}
void fwt_or(int *A,int f)
{
for(int mid=1,len=2;mid<total;mid<<=1,len<<=1)
for(int p=0;p<total;p+=len)
for(int k=0;k<mid;++k)
add(A[p+mid+k],A[p+k]*f);
}
void fwt_and(int *A,int f)
{
for(int mid=1,len=2;mid<total;mid<<=1,len<<=1)
for(int p=0;p<total;p+=len)
for(int k=0;k<mid;++k)
add(A[p+k],A[p+mid+k]*f);
}
void fwt_xor(int *A,int f)
{
for(int mid=1,len=2;mid<total;mid<<=1,len<<=1)
{
for(int p=0;p<total;p+=len)
{
for(int k=0;k<mid;++k)
{
int x=A[p+k],y=A[p+mid+k];
A[p+k]=(1ll*x+y)%mod;
A[p+mid+k]=(1ll*x-y+mod)%mod;
if(f==-1)
{
A[p+k]=1ll*A[p+k]*inv2%mod;
A[p+mid+k]=1ll*A[p+mid+k]*inv2%mod;
}
}
}
}
}
void init()
{
for(int i=0;i<total;++i)
a[i]=A[i],b[i]=B[i];
}
void print()
{
for(int i=0;i<total;++i)
printf("%d%c",a[i],i==total-1?'\n':' ');
}
void solve1()
{
init();
fwt_or(a,1),fwt_or(b,1);
for(int i=0;i<total;++i) a[i]=1ll*a[i]*b[i]%mod;
fwt_or(a,-1);
print();
}
void solve2()
{
init();
fwt_and(a,1),fwt_and(b,1);
for(int i=0;i<total;++i) a[i]=1ll*a[i]*b[i]%mod;
fwt_and(a,-1);
print();
}
void solve3()
{
init();
fwt_xor(a,1),fwt_xor(b,1);
for(int i=0;i<total;++i) a[i]=1ll*a[i]*b[i]%mod;
fwt_xor(a,-1);
print();
}
int main()
{
scanf("%d",&n);
total=1<<n;
for(int i=0;i<total;++i) scanf("%d",&A[i]);
for(int i=0;i<total;++i) scanf("%d",&B[i]);
solve1();
solve2();
solve3();
return 0;
}