倍增算法

  在上一篇求LCA的文章中,我们使用了倍增的算法(可以认为是二分思想的逆用),在这里我们来简单了解一下倍增算法的思想。

  有这样一个问题,现在有一个数字n,现在要求将n分解为2的幂之和(n = ∑(20 + 21 + 22 + …… + 2i-1 + 2i)),要怎么做?下面来介绍该怎么办,为了说明方便,我们假设n = 9 ,同时设定一个上限值16,也就是从24(令k = 4)开始分解:

  (1)9 < 24, 说明k太大了,将k = k - 1,此时n = 9,k = 3,

  (2)9 > 23,令9 - 23 = 1,继续将k = k - 1,此时n = 1,k = 2,

  (3)1 < 22, 说明k太大了,继续将k = k - 1,此时n = 1,k = 1,

  (4)1 < 21, 说明k太大了,继续将k = k - 1,此时n = 1,k = 0,

  (5)1 = 20,令1 - 20 = 0,n分解完毕。

  总结上面的步骤,可以知道9 = 8 + 1 = 23 + 20 。将以上步骤一般化:,可以得到分解过程实际上就是一个在:预估一个k的上线,然后不断地判断n是否大于等于2k,如果是则n -= 2k,再对k--。以上步骤中有一点可以进行优化,对一个数进行位移操作,左位移就相当于乘以2,那么我们可以对1左位移k位来表示2k这个数字。以上内容具体的实现代码如下:

  

void doubly(int n)    //待分解的数
{
    int tmp = n;
        const int MAX = 20;    //幂的上限
    for(int i = 20; i >= 0; i--) 
    {
        if(tmp >= (1 << i))
        {
            tmp -= (1 << i);
        }
    }
}

 

posted @ 2018-07-28 13:09  potato226  阅读(1745)  评论(0编辑  收藏  举报