关于fwt的一些东西
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; }
https://zerol.me/2019/03/18/CF-102129A/
https://codeforces.com/gym/102129
这题是参考上面那个题解的
\begin{eqnarray}
c_0 &=& (a_1+a_2)(b_1+b_2) \
c_0 + c_1 + c_2 &=& (a_0 + a_1 + a_2)(b_0 + b_1 + b_2) \
c_3 &=& a_2b_2 \
c_1 + c_3 &=& (a_0 + a_2)(b_0 + b_2)
\end{eqnarray}
按照如上化简之后就可以进行4进制下的fwt
//#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; } struct re{ int a,b,c; }; int f(int x) { int k1=0,k2=1; while (x) { int t=x%3; x/=3; k1+=k2*t; k2=k2*4; } return k1; } int m1,m2; const int N=(1<<24)+3; ll a[N]; int b[N]; void g1(ll &xa,ll &xb,ll &xc,ll &xd) { ll a=xa,b=xb,c=xc,d=xd; xa=b+c; xb=a+b+c; xc=c; xd=a+c; } void g11(int &xa,int &xb,int &xc,int &xd) { int a=xa,b=xb,c=xc,d=xd; xa=b+c; xb=a+b+c; xc=c; xd=a+c; } void g2(ll &xa,ll &xb,ll &xc,ll &xd) { ll a=xa,b=xb,c=xc,d=xd; xa=a; xd=c; xb=d-xd; xc=b-xa-xb; } void fwt(int *a,int o) { for (int i=1;i<m2;i*=4) for (int j=0;j<m2;j+=(i*4)) for (int k=0;k<i;k++) { if (o==0) g11(a[j+k],a[j+k+i],a[j+k+2*i],a[j+k+3*i]); } } void fwt(ll *a,int o) { for (int i=1;i<m2;i*=4) for (int j=0;j<m2;j+=(i*4)) for (int k=0;k<i;k++) { if (o==0) g1(a[j+k],a[j+k+i],a[j+k+2*i],a[j+k+3*i]); else g2(a[j+k],a[j+k+i],a[j+k+2*i],a[j+k+3*i]); } } int main() { freopen("3.in","r",stdin); freopen("3.out","w",stdout); ios::sync_with_stdio(false); int n; cin>>n; m1=1,m2=1; rep(i,1,n) m1=m1*3,m2=m2*4; rep(i,0,m1-1) { cin>>a[f(i)];} rep(i,0,m1-1) { cin>>b[f(i)];} fwt(a,0); fwt(b,0); rep(i,0,m2-1) a[i]=a[i]*b[i]; fwt(a,1); rep(i,0,m1-1) cout<<a[f(i)]<<" "; return 0; }
还有k进制下的fwt
https://www.cnblogs.com/reverymoon/p/10197711.html参考这个博客的
这个矩阵是利用单位根
因为要求$T1[x][i]*T2[x][j]=T3[x][k](i \otimes j=k)$
而${w_k}^{xi}*{w_k}^{xj}=w_k^{x(i+j)\%k}$
所以只需要让$T[x][i]={w_k}^{xi}$
\begin{bmatrix}
1& 1 & 1& ... & 1\\
1& w_k^1& w_k^2& ... & w_k^{k - 1}\\
1& w_k^2 & w_k^4& ... & w_k^{2(k - 1)}\\
...& ...& ...& ...& ...\\
1& w_k^{k - 1}& w_k^{2(k - 1)} & ... & w_k^{(k - 1)(k - 1)}
\end{bmatrix}
他的逆矩阵是
$\frac{1}{k}$ \begin{bmatrix}
1& 1 & 1& ... & 1\\
1& w_k^{-1}& w_k^{-2}& ... & w_k^{-(k - 1)}\\
1& w_k^{-2} & w_k^{-4}& ... & w_k^{-2(k - 1)}\\
...& ...& ...& ...& ...\\
1& w_k^{-(k - 1)}& w_k^{-2(k - 1)} & ... & w_k^{-(k - 1)(k - 1)}
\end{bmatrix}
这个代码有需要在写。。