快速冪原文html
快速冪這個東西比較好理解,但實現起來到不老好辦,記了幾回總是忘,今天把它系統的總結一下防止忘記。算法
首先,快速冪的目的就是作到快速求冪,假設咱們要求a^b,按照樸素算法就是把a連乘b次,這樣一來時間複雜度是O(b)也便是O(n)級別,快速冪能作到O(logn),快了好多好多。它的原理以下:工具
假設咱們要求a^b,那麼其實b是能夠拆成二進制的,該二進制數第i位的權爲2^(i-1),例如當b==11時code
11的二進制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,所以,咱們將a¹¹轉化爲算 a2^0*a2^1*a2^3,也就是a1*a2*a8 ,看出來快的多了吧原來算11次,如今算三次,可是這三項貌似很差求的樣子....不急,下面會有詳細解釋。 因爲是二進制,很天然地想到用位運算這個強大的工具:&和>>,&運算一般用於二進制取位操做,例如一個數 & 1 的結果就是取二進制的最末位。還能夠判斷奇偶x&1==0爲偶,x&1==1爲奇。>>運算比較單純,二進制去掉最後一位,很少說了,先放代碼再解釋。htm
int Pow(int a, int b) { int ans = 1; while (b) { if (b & 1) ans *= a ; a *= a; b >>= 1; } return ans; }
代碼很短,死記也可行,但最好仍是理解一下吧,其實也很好理解,以b==11爲例,b=>1011,二進制從右向左算,但乘出來的順序是 a^(2^0)*a^(2^1)*a^(2^3),是從左向右的。咱們不斷的讓base*=base目的便是累乘,以便隨時對ans作出貢獻。blog
其中要理解base*=base這一步:由於 base*base==base2,下一步再乘,就是base2*base2==base4,而後同理 base4*base4=base8,由此能夠作到base-->base2-->base4-->base8-->base16-->base32.......指數正是 2^i ,再看上面的例子,a¹¹= a1*a2*a8,這三項就能夠完美解決了,快速冪就是這樣。get
快速冪取模運算原理:ab mod c=(a mod c)(b mod c)mod c ;class
代碼:原理
int PowMod(int a, int b, int c) { int ans = 1; a %= c; while (b) { if (b & 1) ans = (ans * a) % c; a = (a * a) % c; b >>= 1; } return ans; }