快速冪 取餘運算 講解

2022-07-20 04:03:12 字數 3430 閱讀 8099

2018-8-28 更新

聽說有這麼一種演算法能夠

暴力相乘的話,電腦要計算 \(b\) 次。用快速冪,計算次數在 \(log_2(b)\) 級別,很實用。

(1)如果將 \(a\) 自乘一次,就會變成 \(a^2\) 。再把 \(a^2\) 自乘一次就會變成 \(a^4\) 。然後是 \(a^8\)…… 自乘 \(n\) 次的結果是 \(a^}\) 。對吧……

(2)\(a^xa^y = a^\),這個容易。

(3)將 \(b\) 轉化為二進位制**一下:

比如 \(b = (11)_\) 就是 \((1011)_\) 。從左到右,這些 \(1\) 分別代表十進位制的 \(8,2,1\)。可以說 \(a^ = a^8 × a^2 × a^1\)。

為什麼要這樣表示?因為在快速冪的過程中,我們會把 \(a\) 自乘為 \(a^2\),然後 \(a^2\) 自乘為 \(a^4\)……像上面第一條說的。

過程會是這樣:

(好長,可以不看,如果要閱讀下面的模擬過程的話,要慢慢地看噢)

·假設我們拿到了 \(a\),並且 \(b = 11\)。想求 \(a^\),但是又不想乘11次,有點慢。

·以電腦視角稍稍觀察一下 \(b = 11\),二進位制下是 \(b = 1011\)。

·製作乙個 \(base\)。現在 \(base = a\),表示的是,\(a^1 = a\)。待會 \(base\) 會變的。

·製作乙個 \(ans\),初值 \(1\),準備用來做答案。

while(b > 0)

= a^8 × a^2 × a^1\) 中的「 \(× a^1\) 」存在。所以 $ ans *= base $。

if(b & 1)

ans *= base;

/*關於 b & 1:

「&」美名曰「按位與」。

x & y 是二進位制 x 和 y 的每一位分別進行「與運算」的結果。

與運算,即兩者都為 1 時才會返回 1,否則返回 0。

那麼 b & 1

二進位制b = 1011

1 = 0001

b&1 = 0001

因為 1(二進位制)的前面幾位全部都是 0,

所以只有 b 二進位制最後一位是 1 時,b & 1 才會返回 1。

挺巧妙的,並且很快。)*/

·然後 \(base\) 努力上公升,他通過自乘一次,使自己變成 \(a^2\)。

base *= base;
同時

b >>= 1;
它把(二進位制的)自己每一位都往右移動了。原來的最後第二位,變成了最後第一位!\(b = (101)_2\)。

}
·迴圈二,再看看 \(b\),最後一位還是 \(1\)。這說明有「 \(× a^2\) 」,\(ans *= base\)。

·\(base\) 繼續努力,通過 \(base *= base\) 讓自己變成了 \(a^4\)。然後 \(b\) 也右移

一位。\(b = 10\)。

·迴圈三,可是 \(b\) 的最後一位不再是 \(1\) 了,說明不存在「 \(× a^4\) 」。\(base\) 自我昇華,達到了 \(a^8\)。且 \(b >>= 1\)。這一步中,答案沒有增加,可是畢竟 \(b > 0\),還有希望。

·迴圈四,\(b\) 的最後一位是 \(1\),這說明「 \(×a^8\) 」的存在。$ ans *= base $。由於 \(b\) 再右移一位就是 \(0\) 了,迴圈結束。

總的來說,如果 \(b\) 在二進位製上的某一位是 \(1\),我們就把答案乘上對應的 \(a^}\)。不懂的話,請結合**理解~

int quickpower(int a, int b)//是求a的b次方

return ans;

}

沒錯快速冪有很多種理解方式。

重新開始。若當前 \(p\) 為偶數,咱們不著急,只需把 \(x\) 自乘,然後 $ p /= 2$ (即考慮下一層,下幾層會幫我們乘上 \((x^2)^\)的)。

若當前 \(p\) 為奇數,說明 \(x^p = x*(x^2)^\) 中前面那個 \(x\) 的存在,\(ans *= x\)。然後繼續考慮下一層(下幾層會幫我們乘上 \((x^2)^\)的)。注意,這裡的 \(x\) 不是指題目開始給出的 \(x\),而是當前層的 \(x\) 應有的值,這跟上面的 \(base\) 是一樣的。

也是稍稍模擬一下比較好理解。

·假設我們拿到了 \(x = 3\),並且 \(p = 11\)。想求 \(3^\)。

·第一層迴圈。\(b = 11\),乙個奇數。將 \(3^\) 分解為 \(3^1 * (3^2)^5\) 來看。本層只需把 \(ans *= 3^1\)。那後面的呢?我們到下一層再搞定。下幾層的總目標是讓 \(ans *= (3^2)^5\),也就是讓 \(ans *= 9^5\)。來到下一層的方法是 \(x = 3*3 = 9\) 且 \(b = 11 / 2 = 5\)。

·第二層迴圈幾乎獨立於第一層存在。\(b = 5\),乙個奇數。將 \(9^\) 分解為 \(9^1 * (9^2)^2\) 來看。本層只需把 \(ans *= 9^1\)。那後面的呢?我們到下一層再搞定。下幾層的總目標是讓 \(ans *= (9^2)^2\),也就是讓 \(ans *= 81^2\)。於是 \(x = 9*9 = 81\) 且 \(b = 5 / 2 = 2\)。

·第三層迴圈,\(b = 2\),不是奇數,不著急,只把 \(81^2\) 當作 \((81^2)^1\)。下幾層的總目標是讓 \(ans *= (81^2)^1\)。於是 \(x = 81 * 81 = 6561\),\(b = 2 / 2 = 1\)。

·第四層迴圈,\(b = 1\),是奇數。這時候已經不用看成什麼分解了,\(ans *= 6561\) 就可完成總目標。\(b / 2\) 為 \(0\)。結束迴圈。

**和上面一樣。因為 \(b \& 1\) 與 \(b \mod 2 == 1\) 等效。\(b /= 2\) 與 \(b >>= 1\) 等效。

快速冪經常要結合取餘運算。這裡也講一點。

取餘運算有一些好用的性質,包括:

\((a+b) \mod b = (a \mod b + b \mod b) \mod b\)

\((a×b) \mod b = ((a \mod b) × (b \mod b)) \mod b\)

證明都很簡單,如果要說服自己的話拿起筆試試吧。可設 \(a = k_a × b + r_a\)……

於是快速冪過程中可以

while(b > 0)

base *= base;

base %= m;

b >>= 1;

}

能保證這樣下來最後的結果與「先乘到最後,再取餘」的結果一樣。

快速冪 取餘運算

給你三個整數 b,p,k,求 b p mod k。輸入只有一行三個整數,分別代表 b,p,k。輸出一行乙個字串b p mod k s,其中b,p,k分別為題目給定的值,s為運算結果。對於100 的資料,保證0 leq b,p leq 2 1 leq k leq 2 快速冪的模板題,沒有什麼好說的。有...

模板 快速冪 取餘運算

輸入b,p,k的值,求b p mod k的值。其中b,p,k k為長整型數。輸入輸出格式 輸入格式 三個整數b,p,k.輸出格式 輸出 b p mod k s s為運算結果 輸入輸出樣例 輸入樣例 1 2 10 9 輸出樣例 1 2 10 mod 9 7 硬來當然不是好方法。但是有乙個規律不知道各位...

取餘運算(mod,快速冪)

題目描述 輸入b,p,k的值,求bpmodk的值。其中b,p,k k為長整型數。輸入 輸入b,p,k的值。輸出 求bpmodk的值。輸入樣例 2 10 9 輸出樣例 2 10 mod 9 7 題目分析 對於任何乙個自然數b都有b 2 b 2 b 2 例如 19 2x9 1 所以,b19 b9 9 1...