1. 程式人生 > >學習筆記——快速冪

學習筆記——快速冪

蒟蒻寫文,難免疏忽,歡迎來踩!

快速冪的必要性


在講快速冪之前,有必要闡明快速冪的重要性。 快速冪之所以重要,是因為很多數論的題目都需要快速的求出某數的冪。在這種情況下,樸素演算法的O(n)時間複雜度難以滿足要求,故考慮使用快速冪。   快速冪的思路與實現(PRE)
首先我們來熟悉兩種位運算以及與之等價的十進位制運算。   第一種是向右位移,操作符是>>,操作符的左值是要進行位移的數,右值是位移位數。為了使筆記更加簡潔,我們在此只介紹>>1。>>1是指將被運算元轉換成二進位制後將數整體向右移動一位,以(10000101001) 2
=(1065) 10為例,10000101001>>1=(1000010100) 2=(532) 10。我們可以發現右移一位等價於十進制中的除以2然後下取整。因此我們能得出公式A (2)>>1=[B (10)/2]。其中A (2)=B (10)。對於此結論的證明,我們可以將10進位制數字轉換成2 n的和的形式,然後模擬位移的計算過程。   然後我們來介紹第二種,它是按位和,操作符&,操作符左右值皆為被運算元。由於演算法中我們只需要&1,因此只介紹&1 。按位和要求將二進位制位數較少的數用0補齊。例如我們在計算1065&1的時候實際上我們是在計算(10000101001) 2
&(00000000001) 2。這樣,我們很容易看出來,按位與1的十進位制實質是判斷奇偶。如果左值是偶數,那麼運算結果為0;如果為奇數則為1 。   介紹這兩種位運算的主要目的是節約快速冪的運算時間。當然這些位運算也可以通過正常的操作來實現,但是位運算在速度上略勝一籌。   快速冪的思路與實現
剛才在介紹右位移操作時我們曾經提到任何一個十進位制整數都能轉換成2 n的和的形式。現在假設我們被要求求出a b。那麼我們可以將b分解為之前2的冪的和的形式,並使用右移一位的形式逐位判斷b的各個位。在判斷之後我們還需要對相應的結果進行操作,因此我們要維護一個變數,使之符合當前正在運算的數位,一旦判斷b當前的數位為1,則答案立即乘以維護好的變數。   給出上述思路的C++程式碼:
/*
import guide:
the macro NUM should be defined as a data type e.g. long long
*/
NUM quickPow(NUM a,NUM b){
	NUM ans=1,curr=a;
	while(b!=0){
		if(b&1!=0) ans*=curr;
		curr*=curr;
		b>>=1;
	}
	return ans;
}

 

請注意快速冪本身並不處理上溢的錯誤,一定要按照使用時的要求合理定義變數型別!

 

快速冪的複雜度


 

快速冪演算法的時間複雜度是O(log n),因為快速冪只需要b的二進位制位數次操作。

快速冪演算法的空間複雜度是O(1),並不涉及到空間上的規模問題,因此是常數空間。