C++快速冪詳解


快速冪

關於快速冪這一塊還是需要做一個總結,寫一篇博客捋捋思路,加深理解。

為什么要用快速冪?

例如:現在有一個題目讓你求 a b ,你可能覺得很簡單啊,來一個for循環,循環b-1次就行了。但是如果b非常大的情況下,那這個做法是非常低效的,時間復雜度大致為 O(b)

當用快速冪之后,時間復雜度為O(logn)

快速冪例子

例如我們用快速冪求 2 11

將指數拆分能夠得到如下的結果。

2 11 = 2 2 0 + 2 1 + 2 3

學過進制轉換看到11拆開的樣子肯定會很眼熟,其實這里就是跟二進制有關。

11的二進制為1011 , 11 = 2 3 1 + 2 2 0 + 2 1 1 + 2 0 1

這樣一來,我們求 2 11 就不需要算10次了,現在三次就夠了。

2 11 = 2 2 0 2 2 1 2 2 3

到這里以后,我們可能會覺得后邊的這三項似乎不好求。

不着急,我們先上代碼。

int poww(int a,int b){
    int ans=1,base=a;
    while(b!=0){
        if(b&1!=0)
          ans*=base;
        base*=base;
        b>>=1;
  }
    return ans;
}

代碼短小精悍,但是,我還是不太建議刻意去記它,容易忘。理解之后,自然就記住了。

我們將 2 11 帶入代碼走一遍或許你就能夠理解了。

其實程序就是自左到右求那三項的值。

2 11 = 2 2 0 2 2 1 2 2 3

上邊我們已經知道11的二進制為1011

程序參數a = 2,b =11

ans =1,base = 2

if判斷處,11最后一位明顯是1,那么我們就需要與結果變量res相乘。

其實,這里的相乘的就是 2 2 0 ,乘完之后res = 2.

到第六行代碼處,base自乘。這一步我給大家詳細解釋一下:

base*base = b a s e 2 , b a s e 2 b a s e 2 = b a s e 4 , b a s e 4 b a s e 4 = b a s e 8 , b a s e 8 b a s e 8 = b a s e 16

有沒有發現一個問題,每次自乘的結果如下:

b a s e 2 b a s e 4 b a s e 8 b a s e 16 b a s e 32

我們換種寫法你會更明白:

b a s e 2 1 b a s e 2 2 b a s e 2 3 b a s e 2 4 b a s e 2 5

你會發現和上邊我們要求的一樣。

2 11 = 2 2 0 2 2 1 2 2 3

無非是base = 2

b >>= 1右移一位,他的作用是將1011變成101–>10–>1

b的最后一位為0時,不乘base,為1的時候成base。

2 11 = 2 2 0 2 2 1 2 2 3

這樣我們能夠讓res乘上上邊的三項,而不乘上2^{2^2}

其實就是根據b的二進制來判斷是否乘上二的階乘。

如果b最后一位為1,也就是說 2 x 對b有貢獻,所以我們結果乘上base。

否則,我們結果不需要乘base,但是base需要自乘,因為二進制位中左邊的權重更大一些。

矩陣快速冪,他的思想和快速冪的思想是一樣的。無非就是 底數變為矩陣了。所以你只需定義一下矩陣的乘法即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM