快速冪及快速冪取模運算

        快速冪原文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;
}
相關文章
相關標籤/搜索