
contents
Problem
背景
曾經某 M 被期望值坑,就只是在計算 $x^y mod z$ 時偷偷替換成 $x^{y-1} times x mod z$,結果得到 Time Limit Exceeded。
根據分析 $y = 16$ 時,用二進制表示為 $(10000)_{2}$,若變成 $y = 15$,就會變成 $(01111)_{2}$,通常快速求冪的乘法次數與二進制的 1 個數成正比,所以速度就慢非常多。
|
|
問題描述
讓我們來一場 $x^y mod z$ 的期望值試驗吧,基礎目標是減少乘法次數。
其中 $1 le x, z le 10^{18}$, $0 le y le 2^{2^{20}}$,在這場試驗中展現你的優化吧。
Sample Input
|
|
Sample Output
|
|
Solution
詳細可以參考《資訊安全 - 近代加密 快速冪次計算》那一篇。
| Algorithm | Table Size | #squaring | Average #Multiplication |
|---|---|---|---|
| Right-To-Left | 1: $x^{2^i}$ | $n$ | $n/2$ |
| Left-To-Right | 1: $x$ | $n$ | $n/2$ |
| Left-To-Right(2-bits) | 3: $x$, $x^2$, $x^3$ | $n$ | $3n/8$ |
| Left-To-Right(sliding) | 2: $x$, $x^3$ | $n$ | $n/3$ |
減少乘法次數,但以上期望乘法次數是跟 1 的個數有關,雖然最好是從 $n/2$ 降到 $n/3$,並不表示速度會真的快上 $1.5$ 倍左右,畢竟還有所謂的基礎乘法次數需求,根據實驗下來大約能快個 10% 到 20% 之間,加上 -Ofast 編譯此時的差異又會再少一點,看起來實作方法影響很嚴重。
例如在不加編譯優化參數下
|
|
上述做法會比下述來得快上許多
|
|
最後,產出一個 cheat 版本,使用 L-to-R-2bits 的概念下去擴充,使用 loop unrolling 進行加速,由於會發生不被整除的問題,小測資就靠 L-to-R-sliding 的方案去解決。
在 zerojudge 主機上平台上,隨機測資下的運作情況如下:
| Algorithm | Time |
|---|---|
| Right-To-Left | 5.4s |
| Left-To-Right(2-bits) | 4.9s |
| Left-To-Right(sliding) | 4.8s |
| Left-To-Right-sliding-cheat | 4.2s |
R-to-L
|
|
L-to-R-2bits
|
|
L-to-R-sliding
|
|
L-to-R-sliding-cheat
|
|




近期评论