最朴素的求冪方法
也就是平常使用pow函數,最簡單的實現就是一直累乘,可以得到這樣的代碼:
1 int Pow(int a,int b){ 2 3 int ans = 1; 4 5 for(int i = 0;i < b;i++){ 6 7 ans *= a; 8 9 } 10 11 return ans; 12 13 }
可以看到,算法的時間復雜度是O(n)。為了降低時間復雜度,我們可以使用快速冪算法,將時間復雜度降低到O(logn),n是冪。
快速冪:
首先,快速冪的目的就是做到快速求冪,假設我們要求a^b,
假設我們要求a^b,那么其實b是可以拆成二進制的,該二進制數第i位的權為2^(i-1),例如當b==11時
1 int poww(int a, int b) { 2 int ans = 1, base = a; 3 while (b != 0) { 4 if (b & 1 != 0) 5 { 6 ans *= base; 7 } 8 base *= base; 9 b >>= 1; 10 } 11 return ans; 12 }
以b==11為例,b=>1011,二進制從右向左算,但乘出來的順序是 a^(2^0)*a^(2^1)*a^(2^3),是從左向右的。我們不斷的讓base*=base目的即是累乘,以便隨時對ans做出貢獻。
其中要理解base*=base這一步:因為 base*base==base2,下一步再乘,就是base2*base2==base4,然后同理 base4*base4=base8,由此可以做到base-->base2-->base4-->base8-->base16-->base32.......指數正是 2^i ,再看上面的例子,a¹¹= a1*a2*a8,這三項就可以完美解決了,快速冪就是這樣。
🔺快速冪取模
根據之前的博客同余定理,我們知道
(a*b)%m = ((a%m)*(b%m))%m;
其實快速冪取模也是用到這個
那么根據上面的定理可以推導出另一個定理:
(a^b) mod c = (a * a * a........)%c = ((a%c)*(a%c)*(a%c)*.........)%c = (a%c)^b %c;
這就是快速冪取模
代碼如下:
1 int pow_mod(int a ,int b) 2 { 3 int ans = 1 ; 4 int base = a % c; 5 while(b>0) 6 { 7 if(b&1!=0) 8 ans = (ans *base)%c; 9 base = (base*base)%c; 10 b >>= 1;
11 } 12 return ans; 13 }