<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Zheng_iii 的博客]]></title><description><![CDATA[这是一个正经的博客]]></description><link>https://blog.z3i.com.cn</link><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Mon, 20 Jul 2026 01:51:57 GMT</lastBuildDate><atom:link href="https://blog.z3i.com.cn/feed" rel="self" type="application/rss+xml"/><pubDate>Mon, 20 Jul 2026 01:51:57 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[使用矩阵和张量积构造 FWT]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://blog.z3i.com.cn/notes/1">https://blog.z3i.com.cn/notes/1</a></blockquote><div><p>对于位运算卷积 $C<em>k = \sum</em>{i \oplus j = k} A<em>i B</em>j$（其中 $\oplus$ 为 OR、AND 或 XOR）。</p><p>我们希望构造一个线性变换 $F$，使得变换后的点值可以直接相乘。</p><p>即 $F(C)<em>i = F(A)</em>i \cdot F(B)_i$，然后再通过逆变换 $F^{-1}$ 还原出 $C$。</p><h2 id="or-">OR 卷积</h2><p>要求构造一个线性变换 $F(A) = M \cdot A$，满足：</p><p>$$F(A \cup B)<em>i = F(A)</em>i \cdot F(B)_i$$</p><p>为了找出矩阵 $M$ 必须满足的条件，我们将等式两边进行代数展开。</p><p>设我们要计算的 OR 卷积结果为数组 $C = A \cup B$，即：$$C<em>k = \sum</em>{x \cup y = k} A<em>x B</em>y$$</p><p>根据矩阵乘法，$F(C)<em>i = \sum</em>{k} m<em>{i, k} C</em>k$。</p><p>将 $C<em>k$ 的定义代入：$$F(C)</em>i = \sum<em>{k} m</em>{i, k} \left( \sum<em>{x \cup y = k} A</em>x B_y \right)$$</p><p>我们可以直接枚举所有的 $x$ 和 $y$：$$F(C)<em>i = \sum</em>{x} \sum<em>{y} m</em>{i, x \cup y} A<em>x B</em>y$$</p><p>这说明，在左边的多项式中，项 $A<em>x B</em>y$ 的系数是 $m_{i, x \cup y}$。</p><p>展开等式右边 $F(A)<em>i \cdot F(B)</em>i$</p><p>将变换的定义式直接相乘：
$$
F(A)<em>i \cdot F(B)</em>i = \left( \sum<em>{x} m</em>{i, x} A<em>x \right) \cdot \left( \sum</em>{y} m<em>{i, y} B</em>y \right)
$$
利用乘法分配律展开：
$$
F(A)<em>i \cdot F(B)</em>i = \sum<em>{x} \sum</em>{y} (m<em>{i, x} \cdot m</em>{i, y}) A<em>x B</em>y
$$
这说明，在右边的多项式中，项 $A<em>x B</em>y$ 的系数是 $(m<em>{i, x} \cdot m</em>{i, y})$。</p><p>为了让 $F(A \cup B)<em>i = F(A)</em>i \cdot F(B)<em>i$ 对于任意数组 $A$ 和 $B$ 都恒成立，根据多项式恒等定理，等式两边 $A</em>x B_y$ 的系数必须完全相等。</p><p>由此我们得到了 FWT 的基本约束： $$m<em>{i, x \cup y} = m</em>{i, x} \cdot m_{i, y}$$</p><p>现在我们将问题缩小到 1 位二进制（长度为 $2$，下标仅为 $0$ 和 $1$），利用刚才推导出的约束来求解 $2 \times 2$ 矩阵 $M<em>1$：
$$
M</em>1 = \begin{bmatrix} m<em>{00} &amp; m</em>{01} \ m<em>{10} &amp; m</em>{11} \end{bmatrix}
$$
对于任意行 $i \in {0, 1}$，代入 $x, y \in {0, 1}$ 推导：</p><ol start="1"><li><p>当 $x=0, y=0$ 时：</p><p>$m<em>{i, 0 \lor 0} = m</em>{i, 0} \cdot m<em>{i, 0} \implies m</em>{i, 0} = m_{i, 0}^2$</p><p>解得 $m<em>{i, 0} = 0$ 或 $1$。但如果取 $0$，会导致矩阵的一整列为 $0$ 从而不可逆，因此必须取 **$m</em>{i, 0} = 1$**。</p></li><li><p>当 $x=1, y=1$ 时：</p><p>$m<em>{i, 1 \lor 1} = m</em>{i, 1} \cdot m<em>{i, 1} \implies m</em>{i, 1} = m_{i, 1}^2$</p><p>解得 $m_{i, 1} = 0$ 或 $1$。</p></li></ol><p>这意味着矩阵的每一行只能是 $[1, 0]$ 或 $[1, 1]$。为了让 $M<em>1$ 可逆（两行线性无关），我们取这两行作为矩阵的上下两行，得到：
$$
M</em>1 = \begin{bmatrix} 1 &amp; 0 \ 1 &amp; 1 \end{bmatrix}
$$
由于二进制的按位独立性，整体系数必定是各单比特系数的连乘积。在代数上，这等价于对 $M<em>1$ 求 $n$ 次张量积：
$$
M</em>n = M<em>1 \otimes M</em>1 \otimes \dots \otimes M<em>1
$$
利用张量积的结合律，我们提取出最高位（最左边的 $M</em>1$），把剩下的 $n-1$ 位记为 $M<em>{n-1}$：
$$
M</em>n = M<em>1 \otimes M</em>{n-1} = \begin{bmatrix} 1 &amp; 0 \ 1 &amp; 1 \end{bmatrix} \otimes M<em>{n-1}
$$
将 $M</em>{n-1}$ 作为一个整体乘进去，得到：
$$
M<em>n = \begin{bmatrix} 1 \cdot M</em>{n-1} &amp; 0 \cdot M<em>{n-1} \ 1 \cdot M</em>{n-1} &amp; 1 \cdot M<em>{n-1} \end{bmatrix} = \begin{bmatrix} M</em>{n-1} &amp; 0 \ M<em>{n-1} &amp; M</em>{n-1} \end{bmatrix}
$$
但是现在我们只能做到 $O(4^n)$ ，考虑怎么做到 $O(n2^n)$。</p><p>我们将长度为 $2^n$ 的原数组 $A$ 按最高位切成两半：$A = \begin{bmatrix} A<em>0 \ A</em>1 \end{bmatrix}$。</p><p>将其与拆开后的 $M<em>n$ 相乘：
$$
F(A) = M</em>n \cdot A = \begin{bmatrix} M<em>{n-1} &amp; 0 \ M</em>{n-1} &amp; M<em>{n-1} \end{bmatrix} \begin{bmatrix} A</em>0 \ A<em>1 \end{bmatrix}
$$
按矩阵乘法规则展开：
$$
F(A) = \begin{bmatrix} M</em>{n-1} \cdot A<em>0 \ M</em>{n-1} \cdot A<em>0 + M</em>{n-1} \cdot A<em>1 \end{bmatrix}
$$
由于 $M</em>{n-1} \cdot A<em>0$ 本质上就是对子数组递归做变换，即 $F(A</em>0)$。代入替换后，我们就得到了最终的分治转移方程：
$$
\begin{bmatrix} F(A<em>0) \ F(A</em>1) \end{bmatrix} = \begin{bmatrix} F(A<em>0) \ F(A</em>0) + F(A_1) \end{bmatrix}
$$
有主定理 ：$T(2^n) = 2 \times T(2^{n-1}) + O(2^n) = O(n2^n)$。</p><p>那我们怎么求逆呢。</p><p>张量积的逆等于逆的张量积。所以我们只需对 $M<em>1$ 求逆：
$$
M</em>1^{-1} = \begin{bmatrix} 1 &amp; 0 \ 1 &amp; 1 \end{bmatrix}^{-1} = \begin{bmatrix} 1 &amp; 0 \ -1 &amp; 1 \end{bmatrix}
$$</p><p>$$
F^{-1}(A) = \begin{bmatrix} M<em>{n-1}^{-1} &amp; 0 \ -M</em>{n-1}^{-1} &amp; M<em>{n-1}^{-1} \end{bmatrix} \begin{bmatrix} A</em>0 \ A<em>1 \end{bmatrix} = \begin{bmatrix} M</em>{n-1}^{-1} \cdot A<em>0 \ M</em>{n-1}^{-1} \cdot A<em>1 - M</em>{n-1}^{-1} \cdot A<em>0 \end{bmatrix} = \begin{bmatrix} F^{-1}(A</em>0) \ F^{-1}(A<em>1) - F^{-1}(A</em>0) \end{bmatrix}
$$</p><p>实现还是很简单的，递归写法：</p><pre class="language-cpp lang-cpp"><code class="language-cpp lang-cpp">void OR(int l, int r, int opt)
{
    if(l == r) return;
    int mid = (l + r) &gt;&gt; 1;
    OR(l, mid, opt);
    OR(mid + 1, r, opt);
    int len = mid - l + 1;
    rep(i,l,mid)
    {
        if(opt == 1) a[i + len] += a[i];
        else a[i + len] -= a[i];
    }
}
</code></pre>
<p>非递归写法：</p><pre class="language-cpp lang-cpp"><code class="language-cpp lang-cpp">void OR(Z *f, int opt)
{
    for(int i = 1; i &lt; lim; i &lt;&lt;= 1)
        for(int j = 0; j &lt; lim; j += (i &lt;&lt; 1))
            rep(k,0,i-1)
                if(opt == 1) f[i + j + k] += f[j + k];
                else f[i + j + k] -= f[j + k];
}
</code></pre>
<h2 id="and-">AND 卷积</h2><p>对于与卷积，同理我们需要构造线性变换满足 $m<em>{i, x \cap y} = m</em>{i, x} \cdot m_{i, y}$ 。</p><p>可得满足该条件的矩阵 $M_1$ 为：
$$
\begin{bmatrix} 1 &amp; 1 \ 0 &amp; 1 \end{bmatrix}
$$
读者自证不难。</p><p>然后有：
$$
M<em>n = \begin{bmatrix} 1 &amp; 1 \ 0 &amp; 1 \end{bmatrix} \otimes M</em>{n-1} = \begin{bmatrix} M<em>{n-1} &amp; M</em>{n-1} \ 0 &amp; M_{n-1} \end{bmatrix}
$$</p><p>$$
F(A) = \begin{bmatrix} M<em>{n-1} &amp; M</em>{n-1} \ 0 &amp; M<em>{n-1} \end{bmatrix} \begin{bmatrix} A</em>0 \ A<em>1 \end{bmatrix} = \begin{bmatrix} M</em>{n-1}A<em>0 + M</em>{n-1}A<em>1 \ M</em>{n-1}A_1 \end{bmatrix}
$$</p><p>可得：
$$
\begin{bmatrix} F(A<em>0) \ F(A</em>1) \end{bmatrix} = \begin{bmatrix} F(A<em>0) + F(A</em>1) \ F(A_1) \end{bmatrix}
$$
求逆与 OR 卷积同理：</p><p>对 $M<em>1$ 求逆：
$$
M</em>1^{-1} = \begin{bmatrix} 1 &amp; -1 \ 0 &amp; 1 \end{bmatrix}
$$</p><p>$$
F^{-1}(A) = \begin{bmatrix} M<em>{n-1}^{-1} &amp; -M</em>{n-1}^{-1} \ 0 &amp; M<em>{n-1}^{-1} \end{bmatrix} \begin{bmatrix} A</em>0 \ A<em>1 \end{bmatrix} = \begin{bmatrix} M</em>{n-1}^{-1}A<em>0 - M</em>{n-1}^{-1}A<em>1 \ M</em>{n-1}^{-1}A<em>1 \end{bmatrix}= \begin{bmatrix} F^{-1}(A</em>0) - F^{-1}(A<em>1) \ F^{-1}(A</em>1) \end{bmatrix}
$$</p><pre class="language-cpp lang-cpp"><code class="language-cpp lang-cpp">void AND(Z *f, int opt)
{
    for(int i = 1; i &lt; lim; i &lt;&lt;= 1)
        for(int j = 0; j &lt; lim; j += (i &lt;&lt; 1))
            rep(k,0,i-1)
                if(opt == 1) f[j + k] += f[i + j + k];
                else f[j + k] -= f[i + j + k];
}
</code></pre>
<h2 id="xor-">XOR 卷积</h2><p>在张量积的帮助下，我们推导 XOR 卷积会自然很多。</p><p>约束：$m<em>{i, x \oplus y} = m</em>{i, x} \cdot m_{i, y}$。</p><ol start="1"><li>代入 $x=0, y=0$：</li></ol><p>​    $m<em>{i, 0 \oplus 0} = m</em>{i, 0} \cdot m<em>{i, 0} \implies m</em>{i, 0} = m_{i, 0}^2$</p><p>​    为了防全 $0$ 行，必须取 <strong>$m_{i, 0} = 1$</strong>。第一列全为 $1$。</p><ol start="2"><li>代入 $x=1, y=1$：</li></ol><p>​    $m<em>{i, 1 \oplus 1} = m</em>{i, 1} \cdot m<em>{i, 1} \implies m</em>{i, 0} = m_{i, 1}^2$</p><p>​    已知 $m<em>{i, 0} = 1$，所以 $1 = m</em>{i, 1}^2$，解得 $m_{i, 1} = 1$ 或 $-1$。</p><p>两行分别为 $[1, 1]$ 和 $[1, -1]$：
$$
M<em>1 = \begin{bmatrix} 1 &amp; 1 \ 1 &amp; -1 \end{bmatrix}
$$
有：
$$
M</em>n = \begin{bmatrix} 1 &amp; 1 \ 1 &amp; -1 \end{bmatrix} \otimes M<em>{n-1} = \begin{bmatrix} M</em>{n-1} &amp; M<em>{n-1} \ M</em>{n-1} &amp; -M_{n-1} \end{bmatrix}
$$</p><p>$$
F(A) = \begin{bmatrix} M<em>{n-1}A</em>0 + M<em>{n-1}A</em>1 \ M<em>{n-1}A</em>0 - M<em>{n-1}A</em>1 \end{bmatrix}
$$</p><p>$$
\begin{bmatrix} F(A<em>0) \ F(A</em>1) \end{bmatrix} = \begin{bmatrix} F(A<em>0) + F(A</em>1) \ F(A<em>0) - F(A</em>1) \end{bmatrix}
$$</p><p>对 $M<em>1$ 求逆：
$$
M</em>1^{-1} = \begin{bmatrix} \frac{1}{2} &amp; \frac{1}{2} \ \frac{1}{2} &amp; -\frac{1}{2} \end{bmatrix}
$$
代入：
$$
F^{-1}(A) = \begin{bmatrix} \frac{1}{2}M<em>{n-1}^{-1} &amp; \frac{1}{2}M</em>{n-1}^{-1} \ \frac{1}{2}M<em>{n-1}^{-1} &amp; -\frac{1}{2}M</em>{n-1}^{-1} \end{bmatrix} \begin{bmatrix} A<em>0 \ A</em>1 \end{bmatrix}
$$</p><pre class="language-cpp lang-cpp"><code class="language-cpp lang-cpp">void XOR(Z *f, int opt)
{
    for(int i = 1; i &lt; lim; i &lt;&lt;= 1)
        for(int j = 0; j &lt; lim; j += (i &lt;&lt; 1))
            rep(k,0,i-1)
            {
                Z x = f[j + k], y = f[i + j + k];
                f[j + k] = x + y;
                f[i + j + k] = x - y;
                if(opt == -1)
                {
                    f[j + k] = f[j + k] * i2;
                    f[i + j + k] = f[i + j + k] * i2;
                }
            }
}
</code></pre></div><p style="text-align:right"><a href="https://blog.z3i.com.cn/notes/1#comments">览毕，何不一言？</a></p></div>]]></description><link>https://blog.z3i.com.cn/notes/1</link><guid isPermaLink="true">https://blog.z3i.com.cn/notes/1</guid><dc:creator><![CDATA[Zheng_iii]]></dc:creator><pubDate>Sun, 19 Jul 2026 11:12:19 GMT</pubDate></item></channel></rss>