分析
Or:
\[(x,y)->x,x+y\\ (x^2,(x+y)^2)->(x^2,2xy+y^2) \]And:
\[(x,y)->x+y,y\\ ((x+y)^2,y^2)->(2xy+x^2,y^2) \]Xor:
\[(x,y)->x+y,x-y\\ ((x+y)^2,(x-y)^2)->(x^2+y^2,2xy) \]#include<bits/stdc++.h>
#define ll long long
const int p=998244353;
using namespace std;
const int N=1e6+5;
int n,a[N],b[N],inv2;
int mo(int x) {
return x>=p?x-p:x;
}
namespace OR {
int a[N],b[N];
void FWT(int *a,int len,int op) {
int L=0;
for(;(1<<L)!=len;L++);
for(int j=0;j<L;j++) {
for(int i=0;i<len;i++) {
if(!(i&(1<<j))) {
if(op==1) a[i|(1<<j)]=mo(a[i|(1<<j)]+a[i]);
else a[i|(1<<j)]=mo(a[i|(1<<j)]+p-a[i]);
}
}
}
}
void main() {
for(int i=0;i<(1<<n);i++) {
a[i]=::a[i],b[i]=::b[i];
}
FWT(a,1<<n,1),FWT(b,1<<n,1);
for(int i=0;i<(1<<n);i++) a[i]=(ll)a[i]*b[i]%p;
FWT(a,1<<n,-1);
for(int i=0;i<(1<<n);i++) printf("%d ",a[i]);
puts("");
}
}
namespace AND {
int a[N],b[N];
void FWT(int *a,int len,int op) {
int L=0;
for(;(1<<L)!=len;L++);
for(int j=0;j<L;j++) {
for(int i=0;i<len;i++) {
if(i&(1<<j)) {
if(op==1) a[i^(1<<j)]=mo(a[i^(1<<j)]+a[i]);
else a[i^(1<<j)]=mo(a[i^(1<<j)]+p-a[i]);
}
}
}
}
void main() {
for(int i=0;i<(1<<n);i++) {
a[i]=::a[i],b[i]=::b[i];
}
FWT(a,1<<n,1),FWT(b,1<<n,1);
for(int i=0;i<(1<<n);i++) a[i]=(ll)a[i]*b[i]%p;
FWT(a,1<<n,-1);
for(int i=0;i<(1<<n);i++) printf("%d ",a[i]);
puts("");
}
}
namespace XOR {
int a[N],b[N];
void FWT(int *a,int len,int op) {
int L=0;
for(;(1<<L)!=len;L++);
for(int j=0;j<L;j++) {
for(int i=0;i<len;i++) {
if(i&(1<<j)) {
if(op==1) {
int t=a[i^(1<<j)];
a[i^(1<<j)]=mo(a[i^(1<<j)]+a[i]);
a[i]=mo(t+p-a[i]);
} else {
int t=a[i^(1<<j)];
a[i^(1<<j)]=(ll)(a[i^(1<<j)]+a[i])*inv2%p;
a[i]=(ll)(t+p-a[i])*inv2%p;
}
}
}
}
}
void main() {
for(int i=0;i<(1<<n);i++) {
a[i]=::a[i],b[i]=::b[i];
}
FWT(a,1<<n,1),FWT(b,1<<n,1);
for(int i=0;i<(1<<n);i++) a[i]=(ll)a[i]*b[i]%p;
FWT(a,1<<n,-1);
for(int i=0;i<(1<<n);i++) printf("%d ",a[i]);
puts("");
}
}
int ksm(ll a,int b) {
ll ret=1;
while(b) {
if(b&1) ret=ret*a%p;
a=a*a%p,b>>=1;
}
return ret;
}
int main() {
scanf("%d",&n);
for(int i=0;i<(1<<n);i++) {
scanf("%d",&a[i]);
}
for(int i=0;i<(1<<n);i++) {
scanf("%d",&b[i]);
}
inv2=ksm(2,p-2);
OR::main();
AND::main();
XOR::main();
return 0;
}