2011年7月24日 星期日

SRM 508 Div1 Easy + Medium

Easy: 給了一個正整數$N$和最初放在第$M$格的物件,你可作如下操作﹕

(1) 把$N$除以其任意一個質因數$p$,並捨棄其他不包含該物件的區間。
(2) 把格子向左或右旋轉一下。

目標是要把物件放在第一格。問最少需要多少步才可。

首先一定要把$N$進行質因數分解。另外需要留意的是,兩個操順序後並無一定關係。可以考慮先處理(2)再處理(1)之前,把$N/p$個等分疊在一起,其結果就等價於先進行(1)再進行(2)。所以可以知道答案必定是先進行若干次(也可能完全沒有)劃分,然後考慮向左或向右旋轉至第一格最划算的費用之和。另,因為$M$是以$1$開始算的,所以要處理劃分後的位置必須先把$M$變成以$0$開始才可。假設劃分後$N'=N/p$,$M'=M \bmod{N'}$。剩下來就是怎樣選取劃分了。因為$N \le 1000000$,其互不相同的質因數最多只有$8$個,因此可以考慮枚舉$8!$的劃分順序。

Medium: 給了$N$個正整數$R_1\cdots R_n$,求有多少數數列$A_1\cdots A_n$使得

(1) $\sum_{i=1}^n A_i = A_1 | A_2 \cdots | A_n$。
(2) $A_i \le R_i$。

答案取模$10^9+9$。$1 \le R_i \le 10^{18}$,$1 \le N \le 10 $。

很難的題目。但$N$不大應該可以有一些牽涉$2^N$的動態規劃。未決定狀態之前,首先第條件(1)要求$A_i$必須不能在某一個二進位有多於一個$1$,而且二進位之間的關係是離散的,因此可以考慮二進位$p$為狀態之一。條件(2)限制了決定那個$A_i$的第$p$位應該取值$1$。因為如果某個$A_i$設為$1$的話可能使得$A_i > R_i$;但只要某些條件下不論$A_i$的第$p$位取值多少都不影響條件(2)。例如$R_i = 10101001_{(2)}, A_i = 101*...._{(2)}$,$*$只可以放$0$,否則會違反了條件(2)。但若$R_i = 10101001_{(2)}, A_i = 100*...._{(2)}$,$*$可以取任意值而不影響條件(2)。廣義一點來說,舉凡$A_i$在$p$位以左是$R_i$的前綴的話,則$A_i$在第$p$位的取值必須受$R_i$的$p$位影響,否則可取任意值。這首先說明了兩件事。第一是$p$必須從左至右有依賴性,第二是可以引入一種狀態,標示有多少個$A_i$是不再符合前綴條件。因為$N \le 10$,這個狀態可以用$2^N$來表示。因此便有$f(p, b)$,算出有多少個可行的方案,使得$p$位以左的二進位都符合條件,並且$b$表示了所有不符合$R_i$的集合。注意為方便,我把位元的算法是以$1$為開始的。已知對所有$b$,$f(0, b) = 1$,因為$p = 0$表示決定$A_i$取值的程序已經完成了。否則,其狀態轉移方程如下﹕
\[
f(p, b) = f(p-1, b') + \sum_{i=1}^N v_i \times f(p-1, b_i'')
\]

其中$b'$是代表在$p$位取$0$的情況下,有多少原本還是前綴的$A_i$現在已經不是了,並加入到$b$之中。
$b''_i$則是決定把$A_i$的$p$位取值為$1$,並根據計算$b'$的方法重新計算$b''_i$有些不再是前綴(留意有些必須前綴的數因為第$p$位的$1$被$A_i$佔用了,所以必須在其第$p$位放置$0$並不再是前綴)。有時候$A_i$是前綴並且$R_i$的$p$位是$0$,因此它不能取值$1$,所以不能把$f(p-1, b_i'')$算進去的,因此$v_i = 0$,其餘情況下都是$v_i = 1$。因此本題可以在$O(2^N\times N^2M)$時間內解決,其中$M$表示最長有多少位元。因為$R_i \le 10^{18}$,因此$M \le 60$。

2011年7月22日 星期五

SRM 509 Div1 Easy + Medium

Easy: 給了一個不帶零的正整數$N$,可任意刪除數位(不能全部刪除、也可以不刪)但保持其原來次序,可得一集合$\mathcal{S}$。求$\sum_{i \in \mathcal{S}} i \bmod{9}$。例如$N = 123$則答案是
\[ 123 + 12 + 13 + 23 + 1 + 2 + 3 \equiv 177 \equiv 6 \pmod{9}\]
首先求取模$9$的意義。從上式可知
\[ 123 \equiv 1 + 2 + 3\pmod{9}\]
因此其實是問所有數位出現多少次,求和並取模。不難從例子發現,若$N$是一$L$位整數,則每個數位會出現$2^{L-1}$次。設$d(N)$是$N$的數位之和,則答案顯然是\[d(N)\times 2^{L-1} \bmod{9}\]
注意$2^{L-1}$可以超越整數範圍。

Medium: 給了一個字串$S$,並只給了幾種特定的操作,其操作形式只有三種。
(1) 在字串內刪除其中一個為$a$的字元,費用為$w_1$。
(2) 在字串內把其中一個為$a$的字元變成$b$,費用為$w_2$。
(3) 在字串加上一個為$a$的字元(可以在字串前後加上),費用為$w_3$。

現給予$R$種互不相同的操作,問把$S$變成迴文的最少費用。

處理這類字串成問題通常是考慮動態規劃狀態$F(x, y)$,即最少把子字串$S_{x\cdots y-1}$修改成迴文的最小費用。

先考慮簡化版問題﹕允許任意操作,並且一律費用為$1$。那麼其狀態轉移方程可以簡單描述成
\[F(x, y) = \begin{cases} 0 & \text{if $y-x \le 1$} \\ F(x+1, y-1) & \text{if $S_x = S_{y-1}$} \\ \min(F(x+1, y), F(x, y-1)) + 1 & \text{otherwise}\end{cases}\]
但套在這道問題又是否可行呢?首先留意到並非任意操作都可行,所以狀態方程必須因應對應字元而再設計。其次是任意操作的費用不再單純是$1$,意味著若把上述方程的費用$1$寫成通用的$W_{S_x,S_y}$,那麼其意義不只限於單次操作使得$S_x$和$S_y$匹配,而是可以經過一系列操作令$W_{S_x,S_y}$最少化。先考慮$C_{a,b}$,即最少費用把字元$a$修改成字元$b$,然後$W_{a,b}$則可經如下公式求得
\[W_{a,b} = \min_{c}\{C_{a,c} + C_{b,c}\}\]
這引伸了另一個問題﹕如何求$C_{a,b}$?可以想像到的是最短路算法。但首先留意求算需要周全考慮所有操作﹕如果只考慮改變字元的話是不夠的,因為可能最小費用操作可以循這種方式獲得﹕修改$\rightarrow$刪除$\rightarrow$加入$\rightarrow$修改。可見刪除和加入這兩種一般難以用最短路方式描述的操作是可以出現在最小費用操作的任意位置中。解決這個問題的一種思路是﹕何不可以把這兩種操作歸約成修改操作?留意兩種操作可以這樣看的﹕
(1)刪除﹕把字元$a$修改成字元$\emptyset$。
(1)加入﹕把字元$\emptyset$修改成字元$a$。
因此我們只需把空字元$\emptyset$列為可考慮修改字元的話,那麼$C_{a,b}$即可以用最短路
\[C_{a,b} = \min_{c \in \{\text{`a', `b', $\cdots$ `z', $\emptyset$}\}}\{C_{a,c} + C_{c, b}\}\]
求得,因此亦得到$W_{a,b}$。現在重新考慮狀態轉移方程,留意因為費用不再全部都是$1$的關係,因此我們把簡化版的方程的$S_x = S_y$情況一併歸約至一般情況之中,即可得解決本題的方程,如下﹕
\[F(x, y) = \begin{cases} 0 & \text{if $y-x \le 1$} \\ \min(F(x+1, y), F(x, y-1)) + W_{S_x,S_y} & \text{otherwise}\end{cases}\]

2011年7月15日 星期五

SRM 512 Div1 Easy + Medium

因為這次SRM是$2$的冪,所以題目分數也別出心裁的改為$2$的冪。

Easy: 假設某餐店只開$N$日,每日也賣出$M$款菜式。每日每款菜式的價格都有所不同。這餐廳有點古怪,要求你必須一天只買一款菜式;第$i$天買了第$j$款菜式的話必須在$i+7$天買第$j$款菜式;一旦你在第$i$天沒有光顧的話以後都不可以光顧該餐廳。你有$K$元在手,問最多能光顧這餐廳多少天。

算是比較容易的題。首先問題可以轉化為:能不能連續光顧$k$天?設這函數是$f(k)$的話我們就是求最大的$k$使得$f(k) = true$。當然由於$k$很小,線性枚舉所有$f(k)$即可。那麼判斷答案實在是很容易的–設$v_{i, j}^k$是在這連續$k$天內每星期$i$都買菜式$j$的總支出。判斷$f(k)$則只需檢查\[\sum_{i=1}^7 \min_{1\le j\le M}v_{i,j}^k \le K\]即可。

Medium: 一個泛費波那契數列是指任意正整數$f_0, f_1$為數列的首兩個元素,並且其數列遵從遞迴式$f_k = f_{k-1} + f_{k-2}, k > 1$。任何其子序列則稱為泛費波那契子數列。假設有一個正整數集$S$,當中有$N$個各不相同的整數。題目要求從$S$中取出兩個不相交的子集$A$和$B$,使得$A$和$B$皆為泛費波那契子數列,並且$A$的最大值必須少於$B$的最小值,而且$A$和$B$皆為上升序列。

乍看起來有點難。首先可以想到的是﹕能不能把$S$排序,然後劃分兩個子集$S_{1\cdots p}$、$S_{p+1\cdots N}$並分別在其中找出$A$和$B$?基於$N$不太大的關係,似乎有點可行,而且問題會簡化為從一個集合中找出最長的泛費波那契子數列。這個如何找呢?現在假設在$S$中找出$A$,可以試著想想枚舉。現在從$S$選出$S_i$和$S_j$,$i < j$,找出所在$S$中最長的泛費波那契子數列且必需包含$S_i$和$S_j$。不過包含$S_i$和$S_j$的子數列並非唯一,例如$\{1, 1, \mathbf 3, 5, \mathbf 8, 13\}$和$\{1, \mathbf 3, \mathbf 8, 11, 19\}$。但是可以留意兩件事﹕(1) $S_i$是數列的第幾個數並沒關係,只需要假定它是第一個就行;(2) 如果假定$S_j$是第$k$個數,則這個數列的存在性是唯一的,而且其唯一性是基於$S_i$之後的那個數。那麼我每只需枚舉$S_i$、$S_j$和$k$基本上憑求得序列的第二個數便可以確定序列。記得費波那契數的矩陣公式嗎?其實我們可以用同樣公式求得答案﹕
\[ \begin{bmatrix}F_k \\ F_{k-1} \end{bmatrix} = \begin{bmatrix} 1 & 1 \\ 1 & 0\end{bmatrix}^{k-1} \begin{bmatrix}F_1 \\ F_0\end{bmatrix}\]
其中$F_k = S_j$,$F_0=S_i$而且$F_1$就是要求的答案。假設該式寫成
\[ \begin{bmatrix}S_j \\ F_{k-1} \end{bmatrix} = \begin{bmatrix} a & b \\ c & d\end{bmatrix} \begin{bmatrix}F_1 \\ S_i\end{bmatrix}\]
則可以得到
\[ S_j = aF_1 + bS_i \]
然後可得$F_1 = \frac{S_j - bS_i}{a}$。於是若$F_1$有整數解,並且$F_1 > 0$,則可以憑$S_i, F_1, S_j$求得整條數列,然後利用set找出$S$內包含的所有序列元素,並從出找出最長的子序列。需留意的是不要重覆計算元素,例如$S_i = 1, S_j = 8, k = 4$(假設$k$是以$0$開始),$F_1=1$。另外枚舉子序列時若$F_1 < S_i$,就算$F_1\in S$也不應算為答案之一,因為題目要求答案序列是上升的。
在預計算$\begin{bmatrix} 1 & 1 \\ 1 & 0\end{bmatrix}^k$的情況下,這算法是$\tilde{O}(N^5)$的,但是也能足夠通過System test。至於$k$應該是多少?因為$S_i \le 10^8$,所以$k \le 50$足夠了。