FWT,FMT,FST,k进制FWT

本文深入探讨了二进制位运算,包括或、与、异或运算,并介绍了快速莫比乌斯变化(FMT)、快速莫比乌斯反演、与卷积、或卷积及k进制FWT等高级概念。通过实例解析,帮助读者理解这些运算在算法优化中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二进制位运算

常见的二进制位运算有:或,与,异或。分别对应了FMT,FMT与FWT。
下面从易到难介绍这几种运算。一下默认幂级数长度为2n2^n2n

FMT

快速莫比乌斯变化,定义也挺简单的。f(S)=∑T⊂Sg(T)f(S) = \sum_{T\subset S} g(T)f(S)=TSg(T)
实际上就是子集和,同理定义快速莫比乌斯反演,即将快速莫比乌斯变化反演即可f^(S)=∑T⊂S(−1)∣S∣−∣T∣g(T)\hat{f}(S) = \sum_{T\subset S} (-1)^{|S| - |T|}g(T)f^(S)=TS(1)STg(T)
然后或卷积就明显可以通过此来优化。
同理就是与卷积。
定义是超集,反之亦然。

FWT

特别解决异或运算的。之后与kkk进制FWTFWTFWT一起写。

FST

就是failed system test
子集卷积。如果单纯做一个或卷积,那么势必答案是不对的,因为要求的条件实际上是

i | j == k && i & j == 0

而或卷积仅仅满足了第一个条件。那么多记一维表示应当有多少个即可。

k进制FWT

k进制下的异或任然是不进位加法,假设符号任然是⊕\oplus,并且是数组A * B = C。
从原理上讲,正变换是我们要做的事情是找到这样一个矩阵www,使得原数组左乘上这个矩阵后还满足A * B = C。
逆变换是左乘这个矩阵的逆矩阵。那么考虑是什么意思
∑i⊕j=kAi∗Bj∗w(x,i)∗w(x,j)=Ck∗w(x,k)\sum \limits_{i \oplus j = k} A_i * B_j * w(x, i) * w(x, j) = C_k * w(x, k)ij=kAiBjw(x,i)w(x,j)=Ckw(x,k)
对比系数可知
w(x,i)∗w(x,j)=w(x,k)  (i⊕j=k)w(x, i) * w(x, j) = w(x, k) \;(i \oplus j = k)w(x,i)w(x,j)=w(x,k)(ij=k)
那么我们的目的即使找到这样的一个矩阵。
那么这样的性质让我们想到单位根:wki∗wkj=wki⊕jw_{k}^{i} * w_{k}^{j}=w_{k}^{i\oplus j}wkiwkj=wkij。从而联想到范德蒙德矩阵
[111...11wk1wk2...wkk−11wk2wk4...wk2(k−1)...............1wkk−1wk2(k−1)...wk(k−1)(k−1)]\begin{bmatrix} 1& 1 & 1& ... & 1\\ 1& w_k^1& w_k^2& ... & w_k^{k - 1}\\ 1& w_k^2 & w_k^4& ... & w_k^{2(k - 1)}\\ ...& ...& ...& ...& ...\\ 1& w_k^{k - 1}& w_k^{2(k - 1)} & ... & w_k^{(k - 1)(k - 1)} \end{bmatrix}111...11wk1wk2...wkk11wk2wk4...wk2(k1)...............1wkk1wk2(k1)...wk(k1)(k1)
然后我们也知道其逆矩阵
1k[111...11wk−1wk−2...wk−(k−1)1wk−2wk−4...wk−2(k−1)...............1wk−(k−1)wk−2(k−1)...wk−(k−1)(k−1)]\frac{1}{k} \begin{bmatrix} 1& 1 & 1& ... & 1\\ 1& w_k^{-1}& w_k^{-2}& ... & w_k^{-(k - 1)}\\ 1& w_k^{-2} & w_k^{-4}& ... & w_k^{-2(k - 1)}\\ ...& ...& ...& ...& ...\\ 1& w_k^{-(k - 1)}& w_k^{-2(k - 1)} & ... & w_k^{-(k - 1)(k - 1)} \end{bmatrix}k1111...11wk1wk2...wk(k1)1wk2wk4...wk2(k1)...............1wk(k1)wk2(k1)...wk(k1)(k1)
然后不就完了?剩下的与正常的FWT一样的。就是答案由len / k的答案组合而来。同时要注意,如果是mod一个NTT质数的时候,有wn0=gmod−1nw_n^0 = g^{\frac{mod - 1}{n}}wn0=gnmod1
下面贴一份代码:

int wn[k];
inline int w(int x, int y) { return wn[(x * y) % k]; }

void FWT(int *a, int len, int coef) {
    static int b[k];
    int v;

    for (int i = 1; i < len; i *= k) {
        for (int j = 0; j < len; j += i * k) {
            for (int k = j; k < j + i; k++) {
                for (int d = 0; d < k; d++) {
                    b[d] = a[k + d * i];
                    a[k + d * i] = 0;
                }

                for (int d = 0; d < k; d++) {
                    v = k + d * i;
                    for (int _d = 0; _d < 4; _d++) {
                        a[v] = add(a[v], 1ll * w(d, coef * _d) * b[_d] % mod);
                    }
                }
            }
        }
    }

    if (coef == -1) {
        int Inv = qpow(len, mod - 2);
        for (int i = 0; i < len; i++) a[i] = 1ll * Inv * a[i] % mod;
    }
}

其中wn[i]=(gmod−1k)iwn[i] = (g^{\frac{mod - 1}{k}})^{i}wn[i]=(gkmod1)icoefcoefcoef111时为正变换,−1-11时为逆变换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值