# The 2025 ICPC Taiwan Technology University Programming Contest (TUPC) 程式碼在 [Github](https://github.com/co0okie/icpc-tupc2025) 上,歡迎自由取用 ## Problem B <br>Diamond Attacker ### Input Format ``` r1 u1 v1 d1 r2 u2 v2 d2 r3 u3 v3 d3 ... ``` - `r`: the order of the diamond attacker - `u`: target x-coordinate - `v`: target y-coordinate - `d`: modulo divisor ### Techinical Specification - $0\le u \le 2^{2025}$ - $0\le |v| \le 2^{2025}$ - $0\le r \le 7$ - $1\le d \le 10^9$ ### Sample Input ``` 1 0 0 9999 1 1 3 9999 2 3 1 9999 ``` ### Sample Output ``` 1 0 2 ``` ### Solution #### Modulo Operation 這題需要對模除運算有一定的了解,包含以下恆等式: $$\DeclareMathOperator{\dp}{dp}\newcommand{\matr}[1]{\mathbf{#1}} (a + b)\bmod d = [(a\bmod d)+(b\bmod d)]\bmod d$$ $$ab \bmod d=(a\bmod d)(b\bmod d)\bmod d$$ 推廣到矩陣: $$ \matr{A}\matr{B}\bmod d=\left(\matr{A}\bmod d\right)\left(\matr{B}\bmod d\right)\bmod d \\ $$ :::spoiler Detailed Derivation $$\begin{align} \matr{A}&=[a_{ij}],\,\textrm{for}\ i=1\ldots m,\,j=1\ldots n \\ \matr{B}&=[b_{ij}],\,\textrm{for}\ i=1\ldots n,\,j=1\ldots p \\ \matr{C}&=[c_{ij}]=\matr{A}\matr{B} \\ \matr{C}\bmod d&=\left[c_{ij}\bmod d\right],\,\textrm{for}\ i=1\ldots m,\,j=1\ldots p \\ &=\left[\left(\sum_{k=1}^na_{ik}b_{kj}\right)\bmod d\right] \\ &=\left[\left(\sum_{k=1}^n\left(a_{ik}b_{kj}\bmod d\right)\right)\bmod d\right] \\ &=\left[\left(\sum_{k=1}^n\left[\left(a_{ik}\bmod d\right)\left(b_{kj}\bmod d\right)\bmod d\right]\right)\bmod d\right] \\ &=\left(\matr{A}\bmod d\right)\left(\matr{B}\bmod d\right)\bmod d \\ \end{align}$$ ::: $$\matr{A}^b\bmod d=\left(\matr{A}\bmod d\right)^b\bmod d$$ :::spoiler Detailed Derivation $$\begin{align} \matr{A}^b\bmod d&=\overbrace{\matr{A}\matr{A}\ldots\matr{A}}^{b}\bmod d \\ &=\overbrace{(\matr{A}\bmod d)(\matr{A}\bmod d)\ldots(\matr{A}\bmod d)}^{b}\bmod d \\ &=\left(\matr{A}\bmod d\right)^b\bmod d \\ \end{align}$$ ::: 後續說明為求方便,省略了一些$\bmod d$,但利用模除運算的分配律性質,只要在每次運算後加上取模即可算出答案。 #### Impossible Condition 首先排除不可能到達的情況,下圖為所有可能到達的地點,觀察可發現,當 $u<|v|$ 或 $(u-v)\bmod 2 \neq 0$ 則不可能到達,此時直接輸出 $0$。 $$\begin{array}{|c|c|c|c|c|c|c|c|c|c|c|} \hline & & & & & & & ○ & & ○ & \\ \hline & & & & & & ○ & & ○ & & ○ \\ \hline & & & & & ○ & & ○ & & ○ & \\ \hline & & & & ○ & & ○ & & ○ & & ○ \\ \hline & & & ○ & & ○ & & ○ & & ○ & \\ \hline & & ○ & & ○ & & ○ & & ○ & & ○ \\ \hline & ○ & & ○ & & ○ & & ○ & & ○ & \\ \hline ○ & & ○ & & ○ & & ○ & & ○ & & ○ \\ \hline & ○ & & ○ & & ○ & & ○ & & ○ & \\ \hline & & ○ & & ○ & & ○ & & ○ & & ○ \\ \hline & & & ○ & & ○ & & ○ & & ○ & \\ \hline & & & & ○ & & ○ & & ○ & & ○ \\ \hline & & & & & ○ & & ○ & & ○ & \\ \hline & & & & & & ○ & & ○ & & ○ \\ \hline & & & & & & & ○ & & ○ & \\ \hline \end{array}$$ #### Highest Path 題目要求找到所有路徑中,包含最大 $y$ 座標的路徑數量。觀察過後可以發現,不論 $r$ 為何、亦不論每步走幾格,此路徑必定為先向右上,再向右下,以下方為例,若目標為$(9, 3)$,◉ 為起點與終點, ● 代表選擇路徑,○ 代表其他可能路徑: $$\begin{array}{|c|c|c|c|c|c|c|c|c|c|c|} \hline & & & & & & & ○ & & ○ & \\ \hline & & & & & & ● & & ○ & & ○ \\ \hline & & & & & ● & & ● & & ○ & \\ \hline & & & & ● & & ○ & & ● & & ○ \\ \hline & & & ● & & ○ & & ○ & & ◉ & \\ \hline & & ● & & ○ & & ○ & & ○ & & ○ \\ \hline & ● & & ○ & & ○ & & ○ & & ○ & \\ \hline ◉ & & ○ & & ○ & & ○ & & ○ & & ○ \\ \hline & ○ & & ○ & & ○ & & ○ & & ○ & \\ \hline & & ○ & & ○ & & ○ & & ○ & & ○ \\ \hline & & & ○ & & ○ & & ○ & & ○ & \\ \hline & & & & ○ & & ○ & & ○ & & ○ \\ \hline & & & & & ○ & & ○ & & ○ & \\ \hline \end{array}$$ 則包含最高 $y$ 座標的路徑僅有一條,因此可將問題拆分為起點 -> 最高點,與最高點 -> 終點兩段。第一段路徑可寫成 $(i,i)$,第二段則可寫成 $(u-j,v+j)$,計算得到交點 $\left({u+v\over 2},{u+v\over 2}\right)$。 #### Number of Highest Path 令 $\dp[i]$ 為可能的路徑數量,其中 $i$ 為與終點的距離,則: - 第一段路為 $(0,0)$ 到 $\left({u+v\over 2},{u+v\over 2}\right)$,可能的路徑數為 $\dp\left[{u+v\over 2}\right]$ - 第二段路為 $\left({u+v\over 2},{u+v\over 2}\right)$ 到 $(u,v)$,可能的路徑數為 $\dp\left[{u-v\over 2}\right]$ 則最終答案,總路徑數為: $$\dp\left[{u+v\over 2}\right]\dp\left[{u-v\over 2}\right]$$ #### Step Size 題目對於一步可以走到的位置定義如下: $$(x+(i+j),\,y+(j-i)),\,0<=i,j<2*r$$ 由此可知,前進一步的最長距離為 $2r-1$,因此定義步長: $$s=2r-1$$ 代表可以選擇前進 $1,2,3,\ldots,2r,2r-1$ 步 #### Dynamic Programming Function 假設步長 $s = 3$,則可以推導出以下規律: $$\begin{split} \textrm{e.g.}\qquad s=3 \\ \dp[0]&&&=1 \\ \dp[1]&=dp[0]&&=1 \\ \dp[2]&=\dp[1]+\dp[0]&&=2 \\ \dp[3]&=\dp[2]+\dp[1]+\dp[0]&&=4 \\ \dp[4]&=\dp[3]+\dp[2]+\dp[1]&&=7 \\ \dp[5]&=\dp[4]+\dp[3]+\dp[2]&&=13 \\ &\vdots \\ \end{split}$$ 舉例來說, $\dp[2]$ 可以理解為「走到 $2$ 的路徑數 $=$ 走到 $1$ 的路徑數 $+$ 走到 $0$ 的路徑數」。 以 piecewise function 表示: $$ \dp[i]=\begin{cases} 0 & i\lt 0 \\ 1 & i=0 \\ \sum_{j=1}^{s}\dp[i-j] & i \gt 0 \\ \end{cases}$$ #### Matrix Representation of Dynamic Programming Function 對於 $i \gt 0$,可以以一個 $s\times s$ 矩陣與 $s\times 1$ 陣列相乘表示其關係: $$ \begin{bmatrix} \dp[i-s+1] \\ \dp[i-s+2] \\ \dp[i-s+3] \\ \dp[i-s+4] \\ \vdots \\ \dp[i-2] \\ \dp[i-1] \\ \dp[i] \\ \end{bmatrix}=\begin{bmatrix} 0 & 1 & 0 & 0 & \cdots & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & \cdots & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & \cdots & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & \cdots & 0 & 0 & 0 \\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\ 0 & 0 & 0 & 0 & \cdots & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & \cdots & 0 & 0 & 1 \\ 1 & 1 & 1 & 1 & \cdots & 1 & 1 & 1 \\ \end{bmatrix}\begin{bmatrix} \dp[i-s] \\ \dp[i-s+1] \\ \dp[i-s+2] \\ \dp[i-s+3] \\ \vdots \\ \dp[i-3] \\ \dp[i-2] \\ \dp[i-1] \\ \end{bmatrix} $$ 將上述等式表示為: $$\matr{x}_i=\matr{A}\matr{x}_{i-1}$$ 利用其遞迴關係,可以一路追溯到初始狀態 $\matr{x}_{0}$: $$\matr{x}_i=\matr{A}\matr{A}\matr{x}_{i-2}=\matr{A}^{2}\matr{x}_{i-2}=\matr{A}^3\matr{x}_{i-3}=\cdots=\matr{A}^{i}\matr{x}_{0}$$ 其中: $$\matr{x}_{0}=\begin{bmatrix} \dp[-s+1] \\ \dp[-s+2] \\ \dp[-s+3] \\ \dp[-s+4] \\ \vdots \\ \dp[-2] \\ \dp[-1] \\ \dp[0] \\ \end{bmatrix}=\begin{bmatrix} 0 \\ 0 \\ 0 \\ 0 \\ \vdots \\ 0 \\ 0 \\ 1 \\ \end{bmatrix}$$ 因此,對於 $i\gt 0$,只要取得 $\matr{x}_i$ 的最後一項即可得到答案。 #### Fast Matrix Exponentiation 題目定義 $u$ 與 $|v|$ 最大可達 $2^{2025}$,而 $i$ 的大小與其相關,因此需要使用快速冪技巧計算 $\matr{A}^{i}$。另外,因為輸入太大,無法以數字類型(64-bit int)儲存,因此需以十進制陣列儲存,計算快速冪時也以十進制為主。 快速冪的核心概念如下,假設要計算 $\matr{A}^{12345}$ : $$\begin{align} \matr{A}^{12345}&=\left(\matr{A}^{1234}\right)^{10}\matr{A}^5 \\ &=\left(\left(\matr{A}^{123}\right)^{10}\matr{A}^{4}\right)^{10}\matr{A}^5 \\ &=\left(\left(\left(\matr{A}^{12}\right)^{10}\matr{A}^{3}\right)^{10}\matr{A}^{4}\right)^{10}\matr{A}^5 \\ &=\left(\left(\left(\left(\matr{A}^{1}\right)^{10}\matr{A}^{2}\right)^{10}\matr{A}^{3}\right)^{10}\matr{A}^{4}\right)^{10}\matr{A}^5 \\ \end{align}$$ 以代數表示: $$ \matr{A}^b=\matr{A}^{10b^′+r}=\left(\matr{A}^{b^′}\right)^{10}\matr{A}^r \\ ,\quad b\div10=b'\ldots r $$ 因此,只要以左到右遍歷 $b$ 的每一位數,重複10次方、乘 $\matr{A}^r$ 兩個動作就能完成矩陣快速冪,pseudocode 如下: ``` function matPow(A, b): // result = A^b result = idenetity matrix with the same size as A for digit in b: // decimal digits, from left to right result = (result ** 10) * (A ** digit) return result ``` #### Acceleration 上述的2個步驟皆有可加速的地方。若要計算矩陣的 10 次方,可以將其拆分成以下運算: $$\matr{A}^{10}=\matr{A}^2\left(\left(\matr{A}^2\right)^2\right)^2$$ 如此只需要 4 次矩陣乘法即可完成計算。 計算 $\matr{A}^r$ 時,考慮到 $r \in \{0,1,\ldots,9\}$,可以預先建立 Lookup Table `Matrix lut[10]`,需要時直接取用 `lut[r]`,大幅減少計算時間。 最終演算法複複雜度為 $O\left(r^3\log(u)\right)$,$r^3$ 來自矩陣乘法,$\log(u)$ 則是因為要分別遍歷 $u$ 的所有位數。