zoukankan      html  css  js  c++  java
  • 【知识点】FWT

    or卷积:

    大概是给定多项式A,B,求多项式C满足$C(x)=sum limits_{i|j=x}{A(i) imes B(j)}$。

    仔细思考一下,我们可以将A,B分别做一个子集和,然后对位相乘。

    那么乘得的多项式F便满足$F(x)=sum limits_{i|jsubseteq x}{A(i) imes B(j)}$。

    然后我们对F做一个子集差($F(x)=F(x)-sum limits_{isubset x}{F(i)}$),最后得到的就是多项式C。

    如果按FFT的写法,那么DFT就是子集和,IDFT就是子集差。(不过这个做法跟FFT并没有很强的联系)

    and卷积:

    把上文所有的子集改成超集。

    xor卷积:

    唯一一个不一样的。

    我们设$bits(x)$表示x的二进制中1个数的奇偶性。

    那么有$bits(i& x)oplus bits(j& x)=bits((ioplus j)& x)$。(将其拆成若干个1xor之和即可证明)

    考虑构造$A'(x)=sum limits_{i=0}^{2^{n}-1}{(-1)^{bits(i& x)}A(i)}$

    那么$A'(x) imes B'(x)=sum limits_{i=0}^{2^{n}-1}{(-1)^{bits(i& x)}A(i)} imes sum limits_{j=0}^{2^{n}-1}{(-1)^{bits(j& x)}B(j)}$

    $=sum limits_{i=0}^{2^{n}-1}{sum limits_{j=0}^{2^{n}-1}{(-1)^{bits((ioplus j)& x)}A(i) imes B(j)}}$

    $=C'(x)$

    于是就可以了,这构造我也不知道是怎么想到的。

    DFT的时候按二进制第i位01分组,加一下0对0,0对1,1对0,1对1的贡献,代码看起来基本就是w=1的FFT。

    IDFT的时候相当于已知x+y,x-y,让你求x,y。直接算就行。

    代码:

    #include<bits/stdc++.h>
    #define maxn 1000005
    #define maxm 500005
    #define inf 0x7fffffff
    #define mod 998244353
    #define ll long long
    #define rint register ll
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    ll n,m,F[maxn],G[maxn],A[maxn],B[maxn],C[maxn];
    
    inline ll read(){
        ll x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline void fwt_or(ll *a,ll op){
        for(ll l=2;l<=n;l<<=1)
            for(ll i=0;i<n;i+=l)
                for(ll j=i;j<i+(l>>1);j++)
                    a[j+(l>>1)]=(a[j+(l>>1)]+op*a[j]+mod)%mod;
    }
    
    inline void fwt_and(ll *a,ll op){
        for(ll l=2;l<=n;l<<=1)
            for(ll i=0;i<n;i+=l)
                for(ll j=i;j<i+(l>>1);j++)
                    a[j]=(a[j]+op*a[j+(l>>1)]+mod)%mod;
    }
    
    inline void fwt_xor(ll *a,ll op){
        ll inv=(mod+1)>>1;
        for(ll l=2;l<=n;l<<=1)
            for(ll i=0;i<n;i+=l)
                for(ll j=i;j<i+(l>>1);j++){
                    ll x=a[j],y=a[j+(l>>1)];
                    a[j]=(x+y)%mod,a[j+(l>>1)]=(x-y+mod)%mod;
                    if(op==-1) a[j]=a[j]*inv%mod,a[j+(l>>1)]=a[j+(l>>1)]*inv%mod;    
                }
    }
    
    int main(){
        m=read(),n=1<<m;
        for(ll i=0;i<n;i++) F[i]=read();
        for(ll i=0;i<n;i++) G[i]=read();
        memcpy(A,F,sizeof(F));
        memcpy(B,G,sizeof(G));
        fwt_or(A,1),fwt_or(B,1);
        for(ll i=0;i<n;i++) C[i]=A[i]*B[i]%mod;
        fwt_or(C,-1);
        for(ll i=0;i<n;i++) printf("%lld ",C[i]); 
        printf("
    ");
        memcpy(A,F,sizeof(F));
        memcpy(B,G,sizeof(G));
        fwt_and(A,1),fwt_and(B,1);
        for(ll i=0;i<n;i++) C[i]=A[i]*B[i]%mod;
        fwt_and(C,-1);
        for(ll i=0;i<n;i++) printf("%lld ",C[i]); 
        printf("
    ");
        memcpy(A,F,sizeof(F));
        memcpy(B,G,sizeof(G));
        fwt_xor(A,1),fwt_xor(B,1);
        for(ll i=0;i<n;i++) C[i]=A[i]*B[i]%mod;
        fwt_xor(C,-1);
        for(ll i=0;i<n;i++) printf("%lld ",C[i]); 
        printf("
    ");
        return 0;
    }
    FWT
  • 相关阅读:
    显示Unicode 字节的对应字符的小技巧
    apktool 打包解包apk的总结
    Android Studio下载新的AVD映像把C盘给占满了
    微信开发记录
    node.js版本升级
    Cordova+FrameWork7开发简单教程
    centos安装 Falcon+
    centos7安装 go
    bash: /home/aprilpeng/.bashrc: Permission denied
    git push问题 objects/pack/tmp_pack_XXXXXX': Permission denied
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13059823.html
Copyright © 2011-2022 走看看