1. 程式人生 > 其它 >Ducci Sequence題解

Ducci Sequence題解

題目翻譯

對於一個序列 \((a_1, a_2, a_3, ···, a_n)\) 進行以下操作:

\[(a_1, a_2, a_3, ···, a_n)→(|a_1 − a_2 |, |a_2 − a_3 |, ···, |a_n − a_1 |) \]

請問這個序列最後會不會變成 \((0, 0, ···, 0)\) 。若沒有變成全是 \(0\) 的序列, 則序列必定會經過多輪操作後進入一個迴圈, 如:

\[(4, 2, 0, 2, 0) → (2, 2, 2, 2, 4) → \]\[( 0, 0, 0, 2, 2) \]\[ → (0, 0, 2, 0, 2) → (0, 2, 2, 2, 2) → (2, 0, 0, 0, 2) → (2, 0, 0, 2, 0) → (2, 0, 2, 2, 2) → (2, 2, 0, 0, 0) → (0, 2, 0, 0, 2) → (2, 2, 0, 2, 2) → (0, 2, 2, 0, 0) → (2, 0, 2, 0, 0) → (2, 2, 2, 0, 2) → (0, 0, 2, 2, 0) → (0, 2, 0, 2, 0) → (2, 2, 2, 2, 0) → \]\[( 0, 0, 0, 2, 2) \]\[... \]

資料範圍:

\(n \leq 15\)

\(a_i \leq 1000\)

思路詳解\

對於這個序列, 由於沒有 \(+\) 運算並且在絕對值下所有值永遠非負, 所以最大值一定不會變大。所以就可以論證題目是正確的所以我們就可以發現, 如果一次操作後這個序列的最大值沒有變, 那就表明剛才這個序列的其中一個最大值的旁邊有個零(\(|a - b| < a(b \neq 0), |a - 0| = a\))也就是:\((···, a_{max}, 0, ···)\)或者\((···, 0, a_{max}, ···)\), 其實這兩者是等價的。那如果再來一次操作最大值還是沒變, 那麼我們就可以知道要麼是上次操作將 \(a_{max}\)

又減成了 \(0\) , 要麼就是 \(0\) 沒有變或 \(a_{max}\) 旁邊還有一個 \(0\), 也就是還是保持著存在最大值的旁邊有 \(0\)

以此類推, 就可以發現, 如果不管怎樣操作, 最大值都不變的話, 那隻能是這個序列有且僅有 \(a_{max}\)\(0\) 。就算運氣再差, 我們也可以在這種情況下用暴力, 跑最多 \(2^n\) 次跑出全為 \(0\) 或者重複。 而如果不是這種序列, 根據剛才的擴充套件方式, 我們每次最大值不變都意味著又有一位的值是 \(a_{max}\)\(0\) , 那也就是說, 過了最多 \(n\) 次後, 這種序列就會變成有且僅有 \(a_{max}\)

\(0\) 的序列或最大值減小。

所以, 按照這樣推理, 我們運氣最差也就是最大值從 \(1000\) 一直降到 \(1\) 後開始 \(0\)\(a_{max}\) 。就算是這樣, 我們暴力的時間複雜度依然只有 \(O(n(2^n + na_{max}))\) ,也就是 \(O(716520)\) (???, 什麼神奇的數, 這真的不是我故意的)。這東西是不可能超時的。 而且這只是最劣解, 實際不可能出現這種情況, 也就是說實際操作比算出來的還要快得多, 所以, 這道題根本就不用想複雜的演算法, 只要細心讀題, 認真看資料範圍, 就可以發現這是一道暴力可以解決的題目。

吐槽

這道題是在講 vector 的時候的例題, 可我真的沒看出來怎麼用 vector 。 也沒辦法, 強加上去也沒有意義, 所以打這道題時就直接用的陣列。 不過本著學了就必須用的原則, 打程式碼的時候還是打一打 vector 吧。

關於程式碼和這道題

因為這道題的核心就是推理時間複雜度為什麼合理, 剩下的實現就只是一個暴力的空殼了。 所以, 如果連這種已經將操作過程清清楚楚地打在題目上了的暴力都不自己手打還要來抄, 還要來複制貼上, 那就太沒有意義了。所以說, 就沒有放程式碼了。

還有關於這道題, 肯定很多人都是直接看到這個資料很小, 就直接打暴力就過了, 實際上並沒有弄清楚原理。 如果你只是為了練個碼力, 我也沒有什麼好說的, 但如果你真的想要在思維上的提升, 我覺得這個時間複雜度的推理還是很有必要的。 不過有一說一, 如果你是在一場關鍵的比賽上這樣做的話..., 我只能送你一句話:“天作孽, 尤可恕。 自作孽, 不可活。”