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