程式碼在 Github 上,歡迎自由取用
r
: the order of the diamond attackeru
: target x-coordinatev
: target y-coordinated
: modulo divisor這題需要對模除運算有一定的了解,包含以下恆等式:
推廣到矩陣:
後續說明為求方便,省略了一些,但利用模除運算的分配律性質,只要在每次運算後加上取模即可算出答案。
首先排除不可能到達的情況,下圖為所有可能到達的地點,觀察可發現,當 或 則不可能到達,此時直接輸出 。
題目要求找到所有路徑中,包含最大 座標的路徑數量。觀察過後可以發現,不論 為何、亦不論每步走幾格,此路徑必定為先向右上,再向右下,以下方為例,若目標為,◉ 為起點與終點, ● 代表選擇路徑,○ 代表其他可能路徑:
則包含最高 座標的路徑僅有一條,因此可將問題拆分為起點 -> 最高點,與最高點 -> 終點兩段。第一段路徑可寫成 ,第二段則可寫成 ,計算得到交點 。
令 為可能的路徑數量,其中 為與終點的距離,則:
則最終答案,總路徑數為:
題目對於一步可以走到的位置定義如下:
由此可知,前進一步的最長距離為 ,因此定義步長:
代表可以選擇前進 步
假設步長 ,則可以推導出以下規律:
舉例來說, 可以理解為「走到 的路徑數 走到 的路徑數 走到 的路徑數」。
以 piecewise function 表示:
對於 ,可以以一個 矩陣與 陣列相乘表示其關係:
將上述等式表示為:
利用其遞迴關係,可以一路追溯到初始狀態 :
其中:
因此,對於 ,只要取得 的最後一項即可得到答案。
題目定義 與 最大可達 ,而 的大小與其相關,因此需要使用快速冪技巧計算 。另外,因為輸入太大,無法以數字類型(64-bit int)儲存,因此需以十進制陣列儲存,計算快速冪時也以十進制為主。
快速冪的核心概念如下,假設要計算 :
以代數表示:
因此,只要以左到右遍歷 的每一位數,重複10次方、乘 兩個動作就能完成矩陣快速冪,pseudocode 如下:
上述的2個步驟皆有可加速的地方。若要計算矩陣的 10 次方,可以將其拆分成以下運算:
如此只需要 4 次矩陣乘法即可完成計算。
計算 時,考慮到 ,可以預先建立 Lookup Table Matrix lut[10]
,需要時直接取用 lut[r]
,大幅減少計算時間。
最終演算法複複雜度為 , 來自矩陣乘法, 則是因為要分別遍歷 的所有位數。