快速冪
關於快速冪這一塊還是需要做一個總結,寫一篇博客捋捋思路,加深理解。
為什么要用快速冪?
例如:現在有一個題目讓你求
,你可能覺得很簡單啊,來一個for
循環,循環b-1
次就行了。但是如果b非常大的情況下,那這個做法是非常低效的,時間復雜度大致為 O(b)
。
當用快速冪之后,時間復雜度為O(logn)
。
快速冪例子
例如我們用快速冪求 。
將指數拆分能夠得到如下的結果。
學過進制轉換看到11拆開的樣子肯定會很眼熟,其實這里就是跟二進制有關。
11的二進制為1011
,
這樣一來,我們求
就不需要算10次了,現在三次就夠了。
到這里以后,我們可能會覺得后邊的這三項似乎不好求。
不着急,我們先上代碼。
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;
}
代碼短小精悍,但是,我還是不太建議刻意去記它,容易忘。理解之后,自然就記住了。
我們將 帶入代碼走一遍或許你就能夠理解了。
其實程序就是自左到右求那三項的值。
上邊我們已經知道11的二進制為1011
程序參數a = 2,b =11
ans =1,base = 2
到if
判斷處,11最后一位明顯是1,那么我們就需要與結果變量res
相乘。
其實,這里的相乘的就是
,乘完之后res = 2
.
到第六行代碼處,base自乘。這一步我給大家詳細解釋一下:
base*base = , , ,
有沒有發現一個問題,每次自乘的結果如下:
我們換種寫法你會更明白:
你會發現和上邊我們要求的一樣。
無非是base = 2
。
b >>= 1
右移一位,他的作用是將1011
變成101
–>10
–>1
當b
的最后一位為0時,不乘base,為1的時候成base。
這樣我們能夠讓res
乘上上邊的三項,而不乘上2^{2^2}
。
其實就是根據b的二進制來判斷是否乘上二的階乘。
如果b最后一位為1
,也就是說
對b有貢獻,所以我們結果乘上base。
否則,我們結果不需要乘base,但是base需要自乘,因為二進制位中左邊的權重更大一些。
矩陣快速冪,他的思想和快速冪的思想是一樣的。無非就是 底數變為矩陣了。所以你只需定義一下矩陣的乘法即可。