2021.08.15 FWT快速沃尔什变换
先把模板代码贴在这,其他的明天再写)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+11; const long long mo=998244353; int n,m; ll a[N],b[N],c[N],inv2; ll quickpow(ll now,ll mi) { ll re=1; while(mi) { if(mi&1) re=(re*now)%mo; now=(now*now)%mo;mi>>=1; } return re; } void fwt_or(ll* t,int len,ll f) { ll x,y; for(int midlen=1;midlen<len;midlen<<=1) { for(int st=0;st<len;st+=(midlen<<1)) { for(int i=0;i<midlen;i++) { x=t[st+i];y=t[st+i+midlen]; t[st+i]=x%mo; t[st+i+midlen]=((f*x+y)%mo+mo)%mo; } } } } void fwt_and(ll* t,int len,ll f) { ll x,y; for(int midlen=1;midlen<len;midlen<<=1) { for(int st=0;st<len;st+=(midlen<<1)) { for(int i=0;i<midlen;i++) { x=t[st+i];y=t[st+i+midlen]; t[st+i]=((x+f*y)%mo+mo)%mo; t[st+i+midlen]=y%mo; } } } } void fwt_xor(ll* t,int len,ll f) { ll x,y; for(int midlen=1;midlen<len;midlen<<=1) { for(int st=0;st<len;st+=(midlen<<1)) { for(int i=0;i<midlen;i++) { x=t[st+i];y=t[st+i+midlen]; t[st+i]=(x+y)%mo; t[st+i+midlen]=(x-y+mo)%mo; if(f==-1) t[st+i]=(t[st+i]*inv2)%mo,t[st+i+midlen]=(t[st+i+midlen]*inv2)%mo; } } } } int main() { inv2=quickpow(2,mo-2); scanf("%d",&m); n=(1<<m); for(int i=0;i<n;i++) scanf("%lld",&a[i]); for(int i=0;i<n;i++) scanf("%lld",&b[i]); fwt_or(a,n,1);fwt_or(b,n,1); for(int i=0;i<n;i++) c[i]=(a[i]*b[i])%mo; fwt_or(c,n,-1); for(int i=0;i<n;i++) printf("%lld ",c[i]); printf("\n"); fwt_or(a,n,-1);fwt_or(b,n,-1); fwt_and(a,n,1);fwt_and(b,n,1); for(int i=0;i<n;i++) c[i]=(a[i]*b[i])%mo; fwt_and(c,n,-1); for(int i=0;i<n;i++) printf("%lld ",c[i]); printf("\n"); fwt_and(a,n,-1);fwt_and(b,n,-1); fwt_xor(a,n,1);fwt_xor(b,n,1); for(int i=0;i<n;i++) c[i]=(a[i]*b[i])%mo; fwt_xor(c,n,-1); for(int i=0;i<n;i++) printf("%lld ",c[i]); printf("\n"); return 0; }
浙公网安备 33010602011771号