快速冪的原理及時間復雜度
快速冪
引例:計算219
我們的思路是,把19拆開,拆成2的整數次冪之和,即19=16+2+1,則原式219 = 216+2+1 = 216 × 22 ×21
這樣,19個2相乘就轉化為3個數相乘,並且,由於這3個數的計算方法與二進制有著密切聯系。因此我們可以采取二進制來依次獲得這3個數。
快速冪原理:對於ab,可將b轉換為2進制按權相加式,其中每個有效權位對應一個中間數,通過這些中間數,我們可以大大減少運算量。從而快速進行冪運算。
對於一個十進制數b,如果找到≥b的最小整數c,其中整數c是2的整數次冪,則b可由log2c位二進制數表示(2n
令n = log2c,b = x020 + x121 + x222 + … + xn-12n-1。
再由ab = a^b = a^(x020 + x121 + x222 + … + xn-12n-1),可以減少乘法操作的次數,先是基數21~2n,先進行了n次乘法,再由有效位(b的二進制形式中,數碼為1的位)的位數m,額外進行m-1次的計算,則總共計算了n+m-1次,即得到計算次數不超過log2c + m – 1次。從原來的乘n次變為現在的最多乘2log2n次,因此,時間復雜度由原來的O(b)減小為現在的O(log2b)。
例如,計算26。
對於傳統計算方法,需要將6個底數2相乘即:
26 = 2×2×2×2×2×2 = 64,總共乘6次
而使用快速冪,則只需要分兩步進行:
① 把6轉換為2進制按權相加式:
6D = (0 × 20 + 1 × 21 + 1 × 22)D = 110B這裏基數21變為22(6<23=8,n=3,n-1=2,指數依次為0,1,2),總共乘了2次。
② 計算26 = 2^6 =2^(0 × 20 + 1 × 21 + 1 × 22
把這個式子展開,則得到22 +4 = 22 × 24
由有效位(6的二進制形式中,數碼為1的位)的位數為2,則額外的乘法次數為2-1=1
快速冪,一共進行了3次乘法
又如計算21025
傳統方法要乘1025次
對於快速冪,由21~210共10次,再由有效位(1025的二進制形式中,數碼為1的位)的位數為2,則額外的乘法次數為2-1=1,所以共進行了11次乘法
代碼如下:
1 long long qpow(long long base, long long pow) 2 { 3 long long res = 1; 4 while(pow) 5 { 6 if(pow&1) 7 res *= base; 8 base *= base ; 9 pow>>=1; 10 cnt += 3; 11 } 12 return res; 13 }
通常,由於int類型以及long long類型的數值範圍限制,通常遇到的OJ題目(例如:UPC-7778快速冪求模)需要對運算結果取模:
long long qpow(long long base, long long pow, long long mod) { long long res = 1 % mod; base %= mod; while(pow) { if(pow&1) res = (res * base) % mod; base = (base * base) % mod; pow>>=1; cnt += 3; } return res; }
對比枚舉冪運算的次數,快速冪的確可以減少運算次數
例如求86666 % 999,樣例結果如下:
Enter a, b, p:
8 6666 999
Count of calculation: 44
a^b %p = 406
快速冪的原理及時間復雜度