https://codeforces.ml/gym/102956
这道题是要实现每一位自定义二进制下运算的fwt$A*B=C$ (*是卷积)
跟一般fwt相同,实现过程可以按位进行
考虑构造成$T1A*T2B=T3C$ (*是对应相乘)
将其按照最高位拆开之后,即$A=[A0,A1],B=[B0,B1],C=[C0,C1]$
即要求$T1A(x)*T2B(x)=T3C(x)$
$\sum_{i=1}^{2}T1[x][i]*A[i] * \sum_{j=1}^{2}T2[x][j]*B[j]= \sum_{k=1}^{2}T3[x][k]*C[k]$
所以即要求$T1[x][i]*T2[x][j]=T3[x][k](i \otimes j=k)$
所以只需要找到满足的T1,T2,T3即可以实现,另外要保证T3一定是可逆的,即行列式>0
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#include <immintrin.h> //#include <emmintrin.h> #include <bits/stdc++.h> using namespace std; #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) #define ll long long #define me(x) memset(x,0,sizeof(x)) #define IL inline #define rint register int inline ll rd(){ ll x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x; } char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>void maxa(T &x,T y) { if (y>x) x=y; } template<class T>void mina(T &x,T y) { if (y<x) x=y; } template<class T>void read(T &x) { int f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while(c=gc(),c>47&&c<58) x=x*10+(c^48); x*=f; } const int maxn=1000000; struct cp { ll x,y; cp operator +(cp B) { return (cp){x+B.x,y+B.y}; } cp operator -(cp B) { return (cp){x-B.x,y-B.y}; } ll operator *(cp B) { return x*B.y-y*B.x; } int half() { return y < 0 || (y == 0 && x < 0); } }; ll aa[20][2][2],bb[20][2][2],cc[20][2][2],ah[20][2][2],bh[20][2][2],ch[20][2][2]; char s[30][6]; int h[30],p[30]; void gao() { rep(i,0,15) { rep(j,0,81*81*81-1) { int a[2][2],b[2][2],c[2][2]; me(a); me(b); me(c); int k=j%81; rep(i1,0,1) { rep(j1,0,1) { a[i1][j1]=k%3-1; k/=3; } } k=(j/81)%81; rep(i1,0,1) { rep(j1,0,1) { b[i1][j1]=k%3-1; k/=3; } } k=(j/81)/81; rep(i1,0,1) { rep(j1,0,1) { c[i1][j1]=k%3-1; k/=3; } } bool tt=1; rep(i1,0,1) { int cc=0; rep(j1,0,1) rep(k1,0,1) { if (c[i1][(i>>cc)&1]!=a[i1][j1]*b[i1][k1]) tt=0; cc++; } } if (!tt) continue; int t=c[0][0]*c[1][1]-c[1][0]*c[0][1]; if (t) { h[i]=t; c[0][1]*=-1; c[1][0]*=-1; swap(c[0][0],c[1][1]); rep(i1,0,1) rep(j1,0,1) { aa[i][i1][j1]=a[i1][j1]; bb[i][i1][j1]=b[i1][j1]; cc[i][i1][j1]=c[i1][j1]; } break; } } } } int n,m; void fwt(ll *a,ll b[20][2][2]) { int gg=0; for (int i=1;i<m;i*=2,gg++) for (int j=0;j<m;j+=(i*2)) for (int k=0;k<i;k++) { //cerr<<gg<<" "<<b[gg][0][0]<<" "<<b[gg][0][1]<<" "<<b[gg][1][0]<<" "<<b[gg][1][1]<<endl; ll xx=a[j+k],yy=a[i+j+k]; a[j+k]=b[gg][0][0]*xx+b[gg][0][1]*yy; a[i+j+k]=b[gg][1][0]*xx+b[gg][1][1]*yy; } } const int N=1e6; ll x[N],y[N]; int main() { freopen("3.in","r",stdin); freopen("3.out","w",stdout); ios::sync_with_stdio(false); gao(); cin>>n; ll ans=1; rep(i,0,n-1) { cin>>s[i]; int now=0; dep(j,3,0) now=now*2+s[i][j]-'0'; rep(i1,0,1) rep(j1,0,1) { ah[i][i1][j1]=aa[now][i1][j1]; bh[i][i1][j1]=bb[now][i1][j1]; ch[i][i1][j1]=cc[now][i1][j1]; } ans=ans*h[now]; } m=1; rep(i,1,n) m=m*2; rep(i,0,m-1) cin>>x[i]; rep(i,0,m-1) cin>>y[i]; fwt(x,ah); fwt(y,bh); rep(i,0,m-1) x[i]=x[i]*y[i]; fwt(x,ch); rep(i,0,m-1) x[i]=x[i]/ans; rep(i,0,m-1) cout<<x[i]<<" "; return 0; }