快速冪取餘

來源:互聯網
上載者:User

標籤:style   blog   http   color   for   2014   問題   代碼   

求a^b mod c

 演算法1.

首先直接地來設計這個演算法:

int  ans=1, i;for(i=1;i<=b;i++)    ans*=a;ans%=c;

這個演算法的時間複雜度體現在for迴圈中,為O(b).

這個演算法存在著明顯的問題,如果a和b過大,很容易就會溢出。

那麼,我們先來看看第一個改進方案:在講這個方案之前,要先有這樣一個公式:

a^b mod c=(a mod c)^b

引理:

(a *b) mod c =[ ( a mod c )* (b mod c) ] mod c ;

證明: 設 a mod c =d,b mod c= e;

       則:a=t*c + d ;  b=k*c + e ;

       (a*b)mod c = (t*c+d)(t*c+e)

                 = (tk c^2 + ( te+dk ) *c + d*e) mod c

                 =de mod c

即積的取餘等於取餘的積的取餘.

(a ^ b)mod c 由上述公式迭代即可得到 ( a mod c)^b.

證明了以上的公式以後,我們可以先讓a關於c取餘,這樣可以大大減少a的大小,於是不用思考的進行了改進:

 演算法2:

int ans = 1 , i ;   a = a % c; //加上這一句  for ( i = 1;i<=b;i++)      ans = ans * a;   ans = ans % c;  

既然某個因子取餘之後相乘再取餘保持餘數不變,那麼新算得的ans也可以進行取餘,所以得到比較良好的改進版本。 

演算法3:

int  ans = 1 ,i ;  a = a % c;for(int i = 1;i<=b;i++)     ans = (ans * a) % c; //這裡再取了一次餘 ans = ans % c; 

 

這個演算法在時間複雜度上沒有改進,仍為O(b),不過已經好很多的,但是在c過大的條件下,還是很有可能逾時,所以,我們推出以下的快速冪演算法。 

快速冪取餘依賴於以下公式:


 

那麼我們可以得到以下演算法: 

演算法4: 

int  ans = 1 ,i ; a = a % c; if (b%2==1)  ans = (ans * a) mod c; //如果是奇數,要多求一步,                     可以提前算到 ans 中。k = (a*a) % c;  //我們取a^2 而不是a for( i = 1;i<=b/2;i++)     ans = (ans * k) % c;  ans = ans % c;   


我們可以看到,我們把時間複雜度變成了O(b/2).

當然,這樣子治標不治本。

但我們可以看到,當我們令k = (a * a) mod c時,狀態已經發生了變化,我們所要求的最終結果即為 k^(b/2) mod c

而不是原來的a^b mod c,所以我們發現這個過程是可以迭代下去的。當然,對於奇數的情形會多出一項a mod c,所以為了完成迭代,當b是奇數時,我們通過 ans = (ans * a) % c;

來彌補多出來的這一項,此時剩餘的部分就可以進行迭代了。 

形如上式的迭代下去後,當b=0時,所有的因子都已經相乘,演算法結束。

於是便可以在O(log b)的時間內完成了。

於是,有了最終的演算法:快速冪演算法。 

演算法5:快速冪演算法  

int ans = 1;a = a % c; while(b>0) {       if(b % 2 == 1)          ans = (ans * a) % c;     b = b/2;     a = (a * a) % c;  }  


將上述的代碼結構化,也就是寫成函數: 

long long  PowerMod (int a, int b, int c) {      int  ans = 1;     a = a % c;     while(b>0) {          if(b % 2 = = 1)             ans = (ans * a) % c;         b = b/2;       //   b>>=1;        a = (a * a) % c;     }     return ans; }  


本演算法的時間複雜度為O(logb),能在幾乎所有的程式設計(競賽)過程中通過,是目前最常用的演算法之一。 

 

以下內容僅供參考: 

 擴充:有關於快速冪的演算法的推導,還可以從另一個角度來想。 

a^b%c 求解這個問題,我們也可以從二進位轉換來考慮: 

將10進位的b轉化成2

進位的運算式:

 

注意此處的an要麼為0,要麼為1,如果為0,那麼這一項就是1,這個對應了上面演算法過程中b是偶數的情況;

為1對應了b是奇數的情況.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.