【知识点】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
原文地址:https://www.cnblogs.com/YSFAC/p/13059823.html