Description

\(\scr Portal.\)

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;
}
posted on 2021-02-03 17:03  Oxide  阅读(81)  评论(0编辑  收藏  举报