zoukankan      html  css  js  c++  java
  • n次方

    1、问题描述

    计算 an

    2、算法分析

    先将 n 变一变,寻找新的计算路径。预处理就是变治法的根本

    如果单纯循环执行 n 次相乘,那么时间复杂度为 O(n)。可以利用二进制幂大大改进效率。

    主要思路是:将十进制的 n 转换成二进制的数组序列 b[]。二进制幂求解有两种方法:从左至右二进制幂和从右至左二进制幂。

    1. 从左至右二进制幂

      变换:an = a(b[n]2m + ... + b[0]20)

      先求 n 的二进制串,如:n = 5 => 1 0 1,那么 b[2] = 1, b[1] = 0, b[0] = 1

      二进制求 n 的伪代码:

      Horner(b[0...n], x)  
      k = b[n]  
      for i = n-1 downto 0 do
        p = x*k + b[i]
      return p

      那么 n 用作 a 的指数时意义是什么样的呢:

      ap = a1

      for i = n - 1 downto 0 do

        ap = a(2p+b[i])

    2. 从右至左二进制幂

      n 变换方法与上面相同,然后从 b[0] -> b[n] 方向逐步求解。

      时间复杂度:O(logn)

    3、代码实现

    #include <stdio.h>
    #include <stdlib.h>
    
    /**
      *  @brief  返回 x 的二进制串(数组)
      */
    int GetBinArray(int x, int arr[], int length)
    {
        int idx = 0;
        
        while(x > 0) {
            
            // 获取末位的二进制
            arr[idx++] = (x & 1) ? 1 : 0;
            if (idx == length)
                break;
            
            // 右移两位
            x = x >> 1;
        }
        
        return idx;
    }
    
    /**
      *  @brief   a^n = a^(b[n]2^n + ... + b[0]2^0)= a^(b[n]2^n)* ... * a^b[0]。 b 数组元素不是 1 就是 0
      */
    int Pow_Bin_RightToLeft(int number, int power)
    {
        if (power == 0)
            return 1;
        
        int length = sizeof(int) * 8; // 32
        int *pint = (int *)malloc(length);
        
        // 获取幂的二进制数组
        length = GetBinArray(power, pint, length);
        
        int item = number;
        int ret  = 1;
        
        for (int i = 0; i < length; i++) {
            
            // 二进制值为 1,计入结果
            if (pint[i] == 1)
                ret *= item;
            item *= item;
        }
        free(pint);
        
        return ret;
    }
    
    /**
      *  @brief   a^n = a^(b[n]2^n + ... + b[0]2^0)=((b[n]*2 + b[n-1])*X +  ....)2 + b[0]。 b 数组元素不是 1 就是 0
      */
    int Pow_Bin_LeftToRight(int number, int power)
    {
        if (power == 0)
            return 1;
        
        int length = sizeof(int)*8;
        int *pint = (int *)malloc(length);
        
        length = GetBinArray(power, pint, length);
        
        int ret = number;
        
        for (int i = length - 1 - 1; i >= 0; i--) {
            
            ret *= ret;
            
            if(pint[i] == 1)
                ret *= number;
        }
        
        free(pint);
        
        return ret;
    }
    
    int main()
    {
        int num = 8, power = 6;
        int ret1 = Pow_Bin_RightToLeft(num, power);
        int ret2 = Pow_Bin_LeftToRight(num, power);
        
        printf("Pow_Bin_RightToLeft: %d^%d == %d
    ", num, power, ret1);
        printf("Pow_Bin_LeftToRight: %d^%d == %d
    ", num, power, ret2);
        
        return 0;
    }
    
    Pow_Bin_RightToLeft: 8^6 == 262144
    Pow_Bin_LeftToRight: 8^6 == 262144
    

    4、内容来源

    计算 n 次方--变治法

  • 相关阅读:
    代码大全第二版-阅读笔记01
    进度日报表15
    进度日报表14
    第七周总结
    进度日报表13
    进度日报表12
    进度日报表11
    系统图表联动
    算符优先分析法
    《软件需求模式》阅读笔记(一)
  • 原文地址:https://www.cnblogs.com/dins/p/n-power.html
Copyright © 2011-2022 走看看