关于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;
}
View Code

 

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;
}
View Code

 

还有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}

这个代码有需要在写。。

posted @ 2021-07-07 16:05  尹吴潇  阅读(100)  评论(0编辑  收藏  举报