证明:将n(n为2的幂)个点的位反转环划分为长为j(2的幂)的连续片段,这些片段都是次序等价的(分布式算法)

这个证明让我花了好大力气(可能是我太笨了,貌似同学都做出来了,也没人说这个难),开始想证明,似乎不会,就想偷懒上网找答案,找不到,又回来想……

我觉得关键在于把规律看出来,写个程序,打印几个例子看一看,我就是把16个元素的打印出来,找到规律,虽然说找到规律要证明也要一点工夫,但是,找到规律就是找到了努力的方向,成功就不远了

--

位反转:把一个数的二进制表示倒过来(最低位换到最高位,次低位换到次高位……),比如6的二进制表示为110,反转后是011,即6对应的位反转数为3。对位反转应该要限制二进制表示的位数,因为如果把6表示成4位二进制0110,反转后是6,而不是3.

(这里位反转数是为了称呼方便自造的,Google了一下,似乎没有位反转数这个称呼,也没有bit reverse number的wiki之类,倒是有人以这个为关键词搜索)

举例:

[0..15]对应的位反转数组为0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15

顺便贴一下代码,当然,这远远不是最优的,甚至也不算简洁,说不定还有bug,只供参考

View Code
#include <stdio.h>
//翻转a,翻转的范围为begin到end
unsigned rev(unsigned a, int begin, int end)
{
    for(unsigned i = (1 << begin), j = 1 << end;
            i < j; i <<= 1, j >>= 1){
        //i用来测试低位,j用来测试对称的高位
        if ((a & i) && !(a & j) || !(a & i) && (a & j)) {
            //如果低位为0,高位为1;或者低位为1,高位为0,则需要交换
            a ^= i, a ^= j;//高位翻转,低位也翻转(等同于交换)
        }
    }
    return a;
}
int main(int argc, const char *argv[])
{
    int begin = 0, end = 3;
    for (unsigned int i = 0; i < 16; i++) {
        printf("%u, ", rev(i, begin, end));
    }
    return 0;
}

(次)序等价:两个数组A[1..L],B[1..L](假设每个数组中的元素各不相同),对每个i,j,A[i]<A[j]当且仅当B[i]<B[j]

例如:

6,3,5,9与3,1,2,5是次序等价的

位反转环:环上有n个处理器P(0),P(1)...P(n-1),第k个处理器的id为rev[k](k对应的位反转数)

下图是8个处理器的位反转环

相关概念介绍完毕。

观察n=16的情况:

先尝试分成连续的四个片段(j=4),每组4个元素,下图中用不同颜色标出(这是分成四个片段的情况中最简单的一种:从0开始,因为实际上这是一个环,也有可能从15开始分,那样第一个片段就是15,0,8,4,待会再考虑这种复杂情况)

                f1      (fragment 1)                    f2                                               f3                                            f4

我们要证明这四个片段中,任意两组是(次)序等价的

观察每个片段第一个元素

再观察每个片段第二个元素

再观察每个片段第三个元素

再观察每个片段第四个元素

发现它们都很接近,而且……

                    g1(group 1)                      g2                                    g3                                  g4

你应该已经看出来了,每个片段的第一个元素都是处在最小的1/4部分(g1),同样,每个片段的第二个元素都是处在次大的1/4部分(8,9,10,11)……

这样,它们是次序等价的就是显然的了

那么对于其他的分段方式呢?

可以通过将这种分段平移来得到,平移后是否仍然保持这种“对应位置元素处在同一个group”的性质呢?

显然,仍然是保持的

这样我们就找到了方向,只需要证明:如果rev[i]∈gk,则rev[i+j] ∈gk,其中0≤i≤n -1 – j(在这个特定的例子中,j=4,n=16,rev[i]表示i对应的反转数)

下面就不往下分析了,直接贴解答:

证明:将数组(0,1,2,…,n - 1)按顺序每n/j个元素一组,分为j组,依次记为g1,g2,…gj,其中gk={(k-1)*n/j, (k-1)*n/j+1,…(k-1)*n/j + n/j - 1}

先考虑一种简单的对环 的划分:将(rev[0],rev[1],…,rev[n – 1])按顺序每j个元素划分为一个片段,分为n/j个片段,依次记为f1, f2,… fn/j,下面证明,如果rev[i]∈gk,则rev[i+j] ∈gk,其中0≤i≤n -1 – j

记n=2m,j=2s,n/j=2m-s,考虑gk中每个元素的二进制表示的高s位(第m-s位到第m-1位)代表的二进制值,只需要将每个元素除以2m-s=n/j取下整,即为k-1。因此,同一个组中任意两个元素的高s位相同,任取不同的组中两个元素,它们的高s位不同。

考虑i和i+j,因为j=2s,所以i和i+j的低s位是相同的,也就是说rev[i]和rev[i+j]的高s位是相同的,所以,如果rev[i]∈gk,则rev[i+j] ∈gk

考虑第一个片段(rev[0],rev[1],…,rev[j – 1]),这些元素的高s位两两不同(因为0,1,..,j-1的低s位两两不同),所以第一个片段中的每个元素都来自不同的组(gk),而由于只有j个组,所以,如果将该片段每个元素用其所在的组的符号(gk)代替,则得到g1,g2,…gj的一个排列(简称为该片段对应的g排列)

由于已经证明如果rev[i]gk,则rev[i+j]gk所以每个片段都可以类似地替换为与片段f1相同的g1,g2,…gj的一个排列

由于g1中的元素 < g2中的元素<…<gj中的元素,所以任意两个片段都是序等价的

考虑将所有片段顺时针移动一格,容易发现,每个片段对应的g排列做了一个循环左移(或者右移,取决于观察角度),因此每个片段对应的g排列仍然保持相同

对于一般情况的划分,可以通过这种逐步平移来得到。因此,对将环Rnrev划分为长度为j(j是2的方幂)的连续片段的任意划分,所有这些片段是次序等价的

证毕。

原文地址:https://www.cnblogs.com/fstang/p/2843548.html