Description
Solution
一些闲话:时隔一年再回首这个东西,发现自己啥也不会。
记 \(\text{popcount}(x)\) 为 \(|x|\),那么可以将 \(i\ \text{and}\ j=0\) 转化成 \(|i|+|j|=|i\ \text{or}\ j|\).
于是我们多加一个维度,那么 \(A_{i,s}\) 中的 \(s\) 还表示原数组的下标,\(i\) 则表示二进制中 \(1\) 的个数。那么只有当 \(i=|s|\) 时 \(A_{i,s}\) 值为 \(a_{s}\),否则为零(定义 \(B,C\) 同理)。
根据题意所求即为(\(i=|j|\) 是否满足无所谓,因为我们最后只需要 \(C_{|j|,j}\) 项)
\[C_{i,j}=\sum_{i_1+i_2=i}\sum_{x\ \text{or}\ y=j}A_{i_1,x}B_{i_2,y}
\]
于是对于每个 \(0\leqslant k\leqslant n\) 的 \(A_k,B_k\) 都做一遍 \(\mathtt{FWT}\),那么 \(C_{i,j}\) 其实就是 \(\displaystyle \sum_{i_1+i_2=i}\mathtt{IFWT}(\mathtt{FWT}(A_{i_1})[j]\times \mathtt{FWT}(B_{i_2})[j])\),\(\tt FWT\) 是可加的,所以也可以把 \(\tt IFWT\) 提到外面。复杂度 \(\mathcal O(n^22^n)\).
总之相比而言 \(\tt FMT\) 很没用就是了,不明白为啥我讲 \(\tt FMT\) 的博客那么多阅读量 🥲。
Code
#include <cstdio>
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}
const int mod=1e9+9;
int n,lim,a[22][(1<<20)+5],b[22][(1<<20)+5],c[22][(1<<20)+5],bit[(1<<20)+5];
void FWT_or(int *t,const int op=1) {
for(int i=2;i<=lim;i<<=1)
for(int j=0,p=(i>>1);j<lim;j=j+i)
for(int k=j;k<j+p;++k)
t[k+p]=(0ll+t[k+p]+t[k]*op+mod)%mod;
}
int main() {
n=read(9); lim=1<<n;
rep(i,1,lim-1) bit[i]=bit[i-(i&-i)]+1;
rep(i,0,lim-1) a[bit[i]][i]=read(9);
rep(i,0,lim-1) b[bit[i]][i]=read(9);
rep(i,0,n) FWT_or(a[i]),FWT_or(b[i]);
rep(s,0,lim-1) rep(i,0,n) rep(j,0,i) c[i][s]=(c[i][s]+1ll*a[j][s]*b[i-j][s]%mod)%mod;
rep(i,0,n) FWT_or(c[i],-1);
rep(i,0,lim-1) print(c[bit[i]][i],' '); puts("");
return 0;
}