[NOI2020] 美食家 題解

Saltyfish6發表於2024-10-16

屬於是將矩陣快速冪的絕大部分技巧用到了極致的一道題。

暴力部分

首先我們先考慮一個普通 DP。

定義 \(dp_{t,i}\) 表示在時間為 \(t\) 時到達點 \(i\) 可以得到的愉悅值之和的最大值。

顯然有 \((i,j)\in E \to dp_{t+w,j}=\max(dp_{t,i}+c_j)\)。特判一下當前節點有美食節的情況即可,複雜度 \(\mathcal{O}(T\times (n+m))\)

矩陣快速冪&拆點最佳化

我們先暫時不考慮美食節的情況,這個後面再處理。

觀察到這個 \(T\) 非常的大,但是 \(dp_t\to dp_{t+w}\) 這個東西不太好,我們當然希望是按照普通的矩陣快速冪一樣,是用 \(dp_{t}\to dp_{t+1}\) 的轉移矩陣進行矩陣快速冪最佳化。

我們考慮矩陣快速冪中一個拆點/拆邊的技巧。(為啥我不知道捏)

首先一個直觀的,對於邊 \((i,j,w)\),你可以把他拆成 \((i,e_1,0),(e_1,e_2,0),....(e_{w-1},j,c_j)\)。(拆掉之後這個三元組的含義也變了,最後那個是邊權)

這樣你的轉移式就變成了 \(dp_{t,i}+w\to dp_{t+1,j}\)。這樣就非常容易使用矩陣快速冪最佳化了。

當然這裡有個小細節,由於 DP 是求的 \(\max\) 這裡是 \(\max\) 加矩陣乘法,不是普通的矩陣乘法,這裡說明一下。

但是這樣的話,複雜度仍然達到了 \(\mathcal{O}((n+4\times m)^3\times \log T)\)

我們發現這個 \(n,m\) 根本就不同階,考慮把拆邊變為拆點。

具體來說,我們將點 \(i\) 拆成 \(i_1 \to i_2 \to i_3\to i_4 \to i_5\) 邊權均為 \(0\),對於原圖上的邊 \((i,j,w)\) 對應在拆了點的圖上就是 \((i_w,j_1,c_j)\),可以發現這樣的策略與剛剛拆邊的效果是等價的。

此時時間複雜度來到 \(\mathcal{O}((5\times n)^3\times \log T)\)

特殊點處理

在進行了進一步的最佳化之後,此時我們就需要考慮一下美食節的問題了。

由於美食節會將 \(t_i\) 時,\(c_{x_i}+y_i\),改變我們的轉移矩陣。故我們考慮將 \(t_i\) 看作特殊點,先求出 \(t_i-1\) 時的 \(dp_{t_i-1,x}\),然後對於 \(dp_{t_i,x}\) 進行暴力的 \(\mathcal{O}(n+m)\) 轉移,然後再求出 \(t_{i+1}-1\)\(dp_{t_{i+1}-1,x}\) 的值..... 依此類推。

時間複雜度 \(\mathcal{O}(k\times (n+m)+k\times (5\times n)^3\times \log T)\)

向量乘矩陣最佳化

我們發現我們為了求出 \(t_i-1\) 時的 \(dp\) 值,每次都需要進行 \(\mathcal{O}(5\times n)^3\times \log T)\) 的矩陣快速冪。

有一個很逆天的東西是,轉移矩陣自乘的時間複雜度是 \(\mathcal{O}((5\times n)^3)\),但是初始矩陣乘轉移矩陣複雜度是 \(\mathcal{O}((5\times n)^2)\),而在我們的特殊點處理中我們進行了多次快速冪,大大增加了轉移矩陣的自乘。

假設轉移矩陣是 \(G\),我們考慮預處理出 \(G^{2^0},G^{2^1},...G^{2^{\log T}}\) 的所有矩陣,這樣我們的每次快速冪就是用初始矩陣乘以轉移矩陣,快速冪的總進行復雜度就減少為了 \(\mathcal{O}((5\times n)^2\times \log T \times k)\),總複雜度加上這個預處理就是 \(\mathcal{O}(k\times (n+m)+k\times (5\times n)^2\times \log T+(5\times n)^3\times \log T)\),發現此時可以透過。

程式碼暫時咕咕咕了。