日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

快速幂实现pow函数(从二分和二进制两种角度理解快速幂)

發布時間:2023/12/13 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 快速幂实现pow函数(从二分和二进制两种角度理解快速幂) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 迭代實現快速冪
    • 思路
      • int的取值范圍
      • 快速冪
        • 從二進制的角度來理解
        • 從二分法的角度來理解
    • 代碼
    • 復雜度分析
  • 進階——超級次方
    • 思路
      • 倒序+快速冪
      • 正序+快速冪
    • 代碼
    • 復雜度分析


迭代實現快速冪

實現 pow(x, n) ,即計算 x 的 n 次冪函數(即,xn)。不得使用庫函數,同時不需要考慮大數問題。

示例 1:

輸入:x = 2.00000, n = 10
輸出:1024.00000

示例 2:

輸入:x = 2.10000, n = 3
輸出:9.26100

示例 3:

輸入:x = 2.00000, n = -2
輸出:0.25000
解釋:2-2 = 1/22 = 1/4 = 0.25

提示:

-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104


思路

想用累乘處理冪路子就走窄了,超時是板上釘釘的。

用快速冪的思想才符合題目考察的意圖,在詳說快速冪之前說一個很刁鉆的測試用例 —— n=-2147483648。

int的取值范圍

我們知道:

  • int的取值范圍是-2147483648(-231)到2147483647(231 - 1
  • -2147483648有一位符號位可用,因此2147483647是32位操作系統中最大的符號型整型常量。
  • 當出現這個刁鉆的測試用例時,如果對n粗暴的取絕對值的話,int是容納不下的,因此當 n<0 時, 需要定義一個long long類型變量 m 來存儲 n 的絕對值。

快速冪

從二進制的角度來理解

  • 對于任何十進制正整數 n ,設其二進制為
    則有:

  • 根據以上推導,可把計算 xn 轉化為解決以下兩個問題:

  • 因此,應用以上操作,可在循環中依次計算
    的值,并將所有累計相乘即可。



從二分法的角度來理解

快速冪實際上是二分思想的一種應用。

  • 二分推導: xn = xn/2 × xn/2 = (x2)n/2,令 n/2 為整數,則需要分為奇偶兩種情況(設向下取整除法符號為 “//” ):

  • 冪獲取結果:
  • 根據二分推導,可通過循環 x = x2 操作,每次把冪從 n 降至 n//2 ,直至將冪降為 0 ;
  • 設 sum=1 ,則初始狀態 xn = xn × sum。在循環二分時,每當 n 為奇數時,將多出的一項 x 乘入 sum ,則最終可化至 xn = x0 * sum = sum,返回 sum 即可。
  • 轉自作者:jyd

    算法流程:

  • 當 x = 0 時:直接返回 0 (避免后續 x = 1 / x 操作報錯)。
  • 初始化 sum = 1 ;
  • 當 n < 0 時:把問題轉化至 n≥0 的范圍內,即執行 x = 1/x ,n = - n ;
  • 循環計算:當 n = 0 時跳出;
    • 當 n&1=1 時:將當前 x 乘入 sum(即 sum?=x );
    • 執行 x = x2(即 x?=x );
    • 執行 n 右移一位(即 n>>=1)。
  • 返回 sum。
  • 代碼

    class Solution { public:double myPow(double x, int n) {if(x == 0) return 0;double sum = 1;long long m = n;if(n < 0){x = 1.0/x;m = -m;}while(m > 0){if(m & 1){sum *= x;}x *= x;m >>= 1;}return sum;} };

    復雜度分析

    • 時間復雜度 O(log_2 n): 二分的時間復雜度為對數級別。
    • 空間復雜度 O(1): sum, b 等變量占用常數大小額外空間。

    進階——超級次方

    計算 ab 對 1337 取模,a 是一個正整數,b 是一個非常大的正整數且會以數組形式給出。


    思路

    本題的難點在于對 數組b 的處理,顯然無法將其轉為 一個具體類型,因此解決方法無非就是 在 倒序 or 正序 遍歷數組的同時進行次方處理

    倒序+快速冪

    本質無非就是把上面提到的二進制思想轉為十進制,具體來說:

    223 可以看作 2(10 * 2) + (1 * 3) ,也就是 10242 * 23

    那么我們只需要在第 k 次 倒序遍歷 數組 b 的同時,記錄 a 的 10k-1 次方即可。


    正序+快速冪

    思路源于秦九韶算法,一般地,一元 n 次多項式的求值需要經過 (n+1)?n2\frac{(n+1)*n}{2}2(n+1)?n? 次乘法和 nnn 次加法,而秦九韶算法只需要 nnn 次乘法和 nnn 次加法。大大簡化了運算過程。

    把一個 n 次多項式:

    改寫成如下形式:

    舉個具體的例子,計算 22342^{234}2234

    2234=2200+30+4=2200?230?24=(220?23)10?24=[(110?22)10?23]10?242^{234} = 2^{200+30+4} = 2^{200} * 2^{30} * 2^4 = (2^{20} * 2^3)^{10} * 2^4 = [(1^{10} * 2^2)^{10} * 2^3]^{10} * 2^42234=2200+30+4=2200?230?24=(220?23)10?24=[(110?22)10?23]10?24

    最后一步推導實際上是對規律的歸納,即:以 1 作為初始值 res,每次有 新項 加入時,對 res 執行 res=res10?新項res = res^{10} * 新項res=res10? 的操作。


    代碼

    class Solution {const int MOD = 1337;int quickmul(int x, int n){ // 快速冪實現pow功能if(x == 0) return 0;int sum = 1;while(n){if(n&1) sum = (long)sum * x % MOD;n >>= 1;x = (long)x * x % MOD;}return sum;} public:int superPow(int a, vector<int>& b) { // 倒序int res = 1, n = b.size();for(int i=n-1; i>=0; i--){res = (long)res * quickmul(a, b[i]) % MOD;a = quickmul(a, 10); // 記錄當前 a 的冪}return res;}int superPow(int a, vector<int>& b) { // 正序int res = 1, n = b.size();for(int i : b){res = (long)quickmul(res, 10) * quickmul(a, i) % MOD;// 加入新項時,對 res 執行 res = res^10 * 新項 的操作}return res;} };

    復雜度分析

    • 時間復雜度O(∑i=0n?1log?bi\sum_{i=0}^{n-1}{\log{b_i}}i=0n?1?logbi?): 其中 n 是數組 b 的長度,對每個 bib_ibi? 計算快速冪的時間為 O(log?bi\log{b_i}logbi?)。
    • 空間復雜度O(1): 過程由迭代實現,避免了遞歸方法對棧空間的占用,只需要常數的空間存放若干變量。
    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的快速幂实现pow函数(从二分和二进制两种角度理解快速幂)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。