算法导论30.3 Exercises 答案
30.3-1
经过蝴蝶变换,得到\(A\)的新序列为\(A'=(0,4,3,7,2,5,-1,9)\)。
以下是自底向上的DFT过程:
\(\begin{array}{|l|l|}\hline s&\\\hline 0&[0],[4],[3],[7],[2],[5],[-1],[9]\\\hline 1&[4,-4],[10,-4],[7,-3],[8,-10]\\\hline 2&[14,-3-3i,-8,-3-3i],[15,3+4i,-13,3-4i]\\\hline 3&\left[19,\left(-4+\dfrac{7\sqrt{2}}{2}\right)-\left(4+\dfrac{13\sqrt{2}}{2}\right)i,-6+i,-\left(4+\dfrac{7\sqrt{2}}{2}\right)+\left(4-\dfrac{13\sqrt{2}}{2}\right)i,-1,-\left(4+\dfrac{7\sqrt{2}}{2}\right)-\left(4-\dfrac{13\sqrt{2}}{2}\right)i,-6-i,\left(-4+\dfrac{7\sqrt{2}}{2}\right)+\left(4+\dfrac{13\sqrt{2}}{2}\right)i\right]\\\hline \end{array}\)
30.3-2
考虑图30.6的FFT电路。在第\(s\)个阶段,有\(\dfrac{n}{2^s}\)个蝶形电路组,从上到下分别编号\(0\sim \dfrac{n}{2^s}-1\),在每个蝶形电路组中,有\(2^{s-1}\)个蝶形电路组,假设从上到下编号为\(0\sim 2^{s-1}-1\)。
那么对于第\(k\)条导线,它在第\(s\)阶段是在蝶形电路组\(\left\lfloor\dfrac{\text{rev}(k)}{2^s}\right\rfloor\),在这个组内的编号为\(\text{rev}(k)\bmod {2^{s-1}}\)。
也就是说,对于第\(s\)个阶段第\(g\)个蝶形电路组的的第\(j\)个蝶形电路,其输入和输出的两条引线的编号为\(\text{rev}(g\cdot 2^s+j)\)和\(\text{rev}(g\cdot 2^s+j+2^{s-1})\)。
30.3-3
假设\(k\)是一个01列向量\(k=(b_0,b_1,\dots,b_{n-1})^T\)。那么由于是对向量\(k\)进行逆序,即相当于将位置\(i\)上的比特转移到位置\(n-1-j\)。因此,\(M\)矩阵的构造如下:
\[ m_{ij}= \left \{\begin{aligned} &1 & & \text{if}\quad i+j=n-1 \\ &0 & & \text{if}\quad i+j\neq n-1 \\ \end{aligned}\right. \]
考虑向量\(z=Mk\),那么计算向量\(z_i\)元素的值,有\(\displaystyle{z_i=\sum_{j=0}^{n-1}m_{ij}k_j=k_{n-1-j}}\)。因此构造出的矩阵\(M\)为所求。事实上,\(M\)的形式如下:
\[ \begin{bmatrix} 0 & 0 & 0 & \cdots & 0 & 1\\ 0 & 0 & 0 & \cdots & 1 & 0\\ 0 & 0 & 0 & \cdots & 0 & 0\\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots\\ 0 & 1 & 0 &\cdots & 0 & 0\\ 1 & 0 & 0 &\cdots & 0 & 0 \end{bmatrix} \]
30.3-4
蝴蝶变换的本质是将数组\(a\)中,对若干对数交换位置。因此可以通过BIT-REVERSE-OF
计算出新位置后原地交换。由于\(i =
\text{rev}(\text{rev}(i))\),因此只有当\(\text{rev}(i)<
i\)时才交换这两个数的位置。
1 | BIT-REVERSE-PERMUTATION(a, n) |
\(\star\) 30.3-5
对于\(i\in[0,n)\),输入\(a_i=i+1\)。那么电路相当于计算多项式\(\displaystyle{A(x)=\sum_{i=0}^{n-1}(i+1)\cdot x^i}\),当\(x\neq 1\)时,可以得到\(A(x)=\dfrac{nx^{n+1}-(n+1)x^n+1}{(x-1)^2}\)。(选择这种系数的原因是,确保了不会有任何一个中间电路的输出值是\(0\))
对于\(k\in[0,n)\),考虑计算\(y_k=A(\omega_n^k)\)的值,那么有
\(y_k= \left \{\begin{aligned} &\dfrac{n(n+1)}{2} & & \text{if}\quad k=0 \\ &\dfrac{n}{1-\omega_n^k} & & \text{if}\quad k=1,2,\dots,n-1\\ \end{aligned}\right.\)
其中第二行式子容易得出,因为
\(\begin{aligned} y_k&=\dfrac{n\omega_n^{k(n+1)}-(n+1)\omega_n^n+1}{(\omega_n^k-1)^2}\\ &=\dfrac{n\omega_n^k-(n+1)+1}{(\omega_n^k-1)^2}\\ &=\dfrac{n(\omega_n^k-1)}{(\omega_n^k-1)^2}\\ &=\dfrac{n}{\omega_n^k-1}\\ \end{aligned}\)
可见,\(y_k\)可以以\(O(n)\)的时间全部计算出来。
接下来,对题目中的故障电路输入上面所提供的输入,获得输出\(y'\),并且记录集合\(S=\{k:y_k\neq y_k',k\in[0,n)\}\)。令\(m=\lg n\),对于图中的FFT电路,可见一个错误的输入将会导致两个错误的输出,也就是说,如果第\(i\)个阶段的电路发生故障,那么最终将会导致\(2^{m-i}\)个输出错误。
因此,在这个电路中发生故障的蝶形电路是在阶段\(s=m-\lg |S|\)中。并且可见,对于\(S\)中的所有数,它们都是关于\(2^{s}\)同余的,因此故障蝶形电路所在蝶形电路组的编号为\(\displaystyle{j=\dfrac{\min_{x\in S}x}{2}}\)。接下来求故障蝶形电路所在的蝶形电路组\(g\)。
首先,如果蝶形电路的两个输入均为\(0\),那么两个输出也是\(0\)。这启发我们首先定义多项式\(\displaystyle{A_{l,r}(x)=\sum_{i=0}^{n-1} a_{l,r,i} x^i}\),其中系数如下:
\(a_{l,r,i}= \left \{\begin{aligned} &i+1 & & \text{if}\quad l\le i\le r \\ &0 & & \text{otherwise}\\ \end{aligned}\right.\)
可以发现,\(A_{0,n-1}(x)=A(x)\)。类似的,当\(x\neq 1\)时,可以得到\(A_{l,r}(x)=\dfrac{(l+1)x^l-lx^{l+1}-(r+2)x^{r+1}+(r+1)x^{r+2}}{(x-1)^2}\)
对于\(k\in[0,n)\),考虑计算\(y_{l,r,k}=A_{l,r}(\omega_n^k)\)的值,那么有
\(y_{l,r,k}= \left \{\begin{aligned} &\dfrac{(l+r + 2)(r-l+1)}{2} & & \text{if}\quad k=0 \\ &\dfrac{(l+1)\omega_n^{kl}-l\omega_n^{k(l+1)}-(r+2)\omega_n^{k(r+1)}+(r+1)\omega_n^{k(r+2)}}{(\omega_n^k-1)^2} & & \text{if}\quad k=1,2,\dots,n-1\\ \end{aligned}\right.\)
同样可见,\(y_{l,r,k}\)可以以\(O(n)\)的时间全部计算出来。
那么我们考虑使用二分法来确定电路组\(g\),每次给定对应的输入,判断一个连续的蝶形电路组\([l,r]\)是否包含了一个故障蝶形电路(即输入多项式\(A_{lr}(x)\)并判断输出结果是否正确),如果输出不正确,那么故障的电路确实在这个电路组中。最终需要\(\lg n-s\)次判断即可。
因此,最终我们只需要恰好\(\lg
n-s+1\)次(至多\(\lg
n\)从)的判断。整个找出故障蝶形电路的位置\((s,g,j)\)由程序FIND-FAILED-ADDER
给出:
1 | GEN-POLY(l, r, n) |