1. 程式人生 > >快速冪的原理及時間復雜度

快速冪的原理及時間復雜度

time 我們 back fcc 只需要 pre 遇到 times urn

快速冪

引例:計算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

=c > b,log2c=n)。

令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

快速冪的原理及時間復雜度