• power(乘幂)函数剖析


    近来学习STL,看到power函数的实现感觉挺有趣,记录一下。

    1. 一般情况下,我自己要实现乘幂函数会这样实现:

    int power(int x,size_t n)
    {
        int result = 1;
        while (n--)
            result *= x;
        return result;
    }

    这样即使实现,这里的时间复杂度和n有关,时间复杂度为0(n)。

    2. 看了stl源码实现是这样:

    // Returns __x ** __n, where __n >= 0.  _Note that "multiplication"
    // is required to be associative, but not necessarily commutative.  
    //意思是multiplication要满足结合律,但不需要满足交换律
    
    template <class _Tp, class _Integer, class _MonoidOperation>  
    _Tp __power(_Tp __x, _Integer __n, _MonoidOperation __opr)  //这里第三个参数是一个二元操作函数
    {
        if (__n == 0)
            return identity_element(__opr);           //返回1
        else 
        {
            while ((__n & 1) == 0)                   //如果n为偶数
            {
                __n >>= 1;
                __x = __opr(__x, __x);
            }
    
            _Tp __result = __x;
            __n >>= 1;
            while (__n != 0) 
            {
                __x = __opr(__x, __x);
                if ((__n & 1) != 0)                    //如果n为奇数
                    __result = __opr(__result, __x);
                __n >>= 1;
            }
            return __result;
        }
    }
    
    template <class _Tp, class _Integer>
    inline _Tp __power(_Tp __x, _Integer __n)
    {
        return __power(__x, __n, multiplies<_Tp>());
    }
    
    // Alias for the internal name __power.  Note that power is an extension,
    // not part of the C++ standard.
    
    template <class _Tp, class _Integer, class _MonoidOperation>
    inline _Tp power(_Tp __x, _Integer __n, _MonoidOperation __opr)   //也可以自定义,传进去一个函数
    {
        return __power(__x, __n, __opr);
    }
    
    template <class _Tp, class _Integer>
    inline _Tp power(_Tp __x, _Integer __n)   //默认情况下是乘幂
    {
        return __power(__x, __n);
    }

    这里:当n为偶数时,X^n=(X^2)^(2/n),此时看2/n是否还是偶数,如果是则继续,否则,转向n是奇数的情况;

               当n为奇数时,X^n=X*X^(n-1);

    例如计算5^6=(5^2)^3,也就是计算25^3。

    这种情况和第三种情况类似,只是当n开始为偶数时,比第三种方法的效率更高,n为奇数时,和第三种方法时间复杂度一样。

    3. 第三种实现,和stl源码差不多,只是表示更简洁,和第二种情况相比效率会差点:

    int power(int x, size_t n)
    {
        if(n == 0)
            return 1;
        int result = 1;
        while(n)
        {
            if(n & 1)                    //n为奇数时
                result *= x;            
            n >>= 1;
            x *= x;                 
        }
    return result; }

    如计算5^6是6化为二进制为0110,所以这里5^6=5^2*5^4,这里时间复杂度为0((log2n)+1)

  • 相关阅读:
    HDU1106 排序
    HDU2050 折线分割平面
    HDU2048 神、上帝以及老天爷
    POJ1836 Alignment
    POJ1182 食物链
    HDU2067 小兔的棋盘
    HTML中的ID不能以数字开头
    automake,autoconf使用详解
    How to install Samba server on Ubuntu 12.04
    Netbeans使用UTF-8编码
  • 原文地址:https://www.cnblogs.com/liuamin/p/7107202.html
Copyright © 2020-2023  润新知