淺談 [NOIP 2023]三值邏輯 無限種解法

PassName發表於2024-07-09

淺談 [NOIP 2023]三值邏輯 無限種解法

前言

對於 NOIP 2023,T1 是個人人都會寫的簽到題,對於 T3 則是做法唯一隻能按照提醒的資料範圍一步一步走,對於 T4 則是隻能線段樹最佳化 dp。思維侷限性大,並沒有什麼深度挖掘的意義。直到有一天睡覺的時候又想起來 T2 這個題,覺得有必要把這個題相關的所有方法記錄下來。故於此記錄。

法一:並查集

考慮對於前 20 pts 的解法,理論可以直接列舉所有可能,但是由於可以特判出一些顯然錯誤的方案,所以列舉的方案數是不全的。理論複雜度 \(O(3^n)\) ,而實際遠遠到不了這個複雜度。

對於中間只有賦值操作的 20 pts,直接並查集維護即可。

考慮正解,顯然是有辦法對於並查集解法進行最佳化的。我們要最小化不確定值的個數,那麼首先要知道如何判定誰可以是不確定的數。對於任意一個數 \(x\) ,如果 \(x\) 的祖先是 \(-x\)。或者 \(x\) 的祖先是 \(U\)。直接並查集維護,但是期間有一些細節。對於取相反數,會出現 \(fa[-x]\) 導致下標錯誤,所以要分類討論 。當然,我們在模擬樣例的時候發現,會出現反覆取反的情況,即 \(x\) -> \(-x\) -> \(x\),這樣在執行並查集的時候會陷入死迴圈,所以再開一個 \(v\) 來記錄是否到達過 \(x\)\(-x\)。當然,對於陣列 \(v\) 也會出現下標為 \(<0\) 的情況,所以下標統一上移 \(n\) 。剩下的直接程式碼實現即可。

submission

法二:二分圖

這個題好玩的地方在於,很多種 trick 都可以對這個題使用。

化繁為簡,考慮將 \(T,F,U\) 賦值操作也更改為下面那些型別的操作,\(T\) 更改為 \(x_{n+1}\)\(F\) 更改為 \(-x_{n+1}\)\(U\) 更改為 \(x_{n+2}\)

建立 \(01\) 無向圖,當涉及取反操作時那麼邊權為 \(1\)

對於樣例,我們發現,如果只有 \(T,F\) 那麼結果一定是 \(Unknown\)。所以,如果圖上出現了一個環其邊權為一的邊有奇數條,所以我們現在的任務就是判定是否存在這樣的話,即判二分圖。如果不是二分圖,那麼整個聯通塊都是 \(U\),單獨統計 \(x_{n+2}\),更新答案

submission

法三:拆點 BFS

把所有的賦值操作改為拆點。每操作一次多拆一個點。

  • 操作一:對 \(x\) 建一個新版本賦值,直接實現
  • 操作二、三:對於 \(x\) 建一個新版本,和 \(y\) 得最新版本連邊權為 \(1\)\(0\) 的無向邊,當涉及取反操作時那麼邊權為 \(1\)

考慮初始情況和末尾情況,操作始末狀態相同,需要把每個點始末版本連一條代表相等得邊。然後發現每個連通塊只有三種狀態,且相互獨立。可以 BFS 直接計算。

法四:基環樹

我們仍然借鑑第二個方法找環的思路,但是並不是使用二分圖。

對於我們最後得到結果,只要不是定值就一定可以寫成 \(k \times a_i\)\(k∈[-1,1]\)。我們原來建立的是 \(01\) 無向圖,而我們現在建立的就是一個有邊權的無向圖了。對於 \(a_i\)\(k \times a_j\) 形式,連線 \(i,j\) 邊權為 \(k\)。這樣就建出了基環樹。如果對於一個點其值已知就可以便利圖求聯通塊。

然後,考慮找環。我們再回到解法一所說,如果有 \(x\) 的祖先為 \(-x\) 的情況,就會出現 \(Unknown\),那麼我們就能得出結論,如果我們這個環的邊權乘積為 \(-1\),即化簡後出現了 \(a_x \times -a_y\) 的情況,則整個聯通塊都是 \(U\)

法五:2-SAT

大炮打蒼蠅

2-SAT 可以用來解決有 \(n\) 對二元矛盾組所構成的集合從中任意找一個元素 \(x\) 從而找到與其不矛盾的。

思路非常符合本題,因為本題全是二元組。並且取反操作前邊都能 \(01\) 邊權了,這裡自然也可以定義矛盾。

\(1\)~\(n+m\) 的點表示為 \(T\) 的點,其中 \(x_{k+n}(1≤k≤n)\) 表示在第 \(k\) 次操作被操作的變數的值(操作後)。設 \(n+m+1\)~\(2 * (n+m)\) 表示 \(x_1,...x_{n+m}\)\(F\) 的點。

如果給 \(x_i\)\(U\)\(i\)\(i + n + m\) 連雙向邊。\(x_i\)\(T\)\(i + n + m\)\(i\) 連單向邊。 \(x_i\)\(F\)\(i\)\(i + n + m\) 連單向邊。 \(x_i\) 賦值為 \(x_j\)\(j\) 決定了 \(i\)\(i\) 也可以倒推出 \(j\)\(cur_j\)\(i\) 連雙向邊,\(cur_j + n + m\)\(i + n + m\) 連雙向邊。如果是 \(x_i\) 賦值為 \(¬x_j\)\(j\) 決定了 \(i\)\(i\) 也可以倒推出 \(j\)\(cur_j + n + m\)\(i\) 連雙向邊,\(cur_j\)\(i + n + m\) 連雙向邊。

\(cur_i\) 為當前操作最後一次更新 \(i\) 的操作編號加 \(n\),若沒有則為 \(i\)

之後 SCC 跑 Tarjan 縮點就好,\(scc_{res_i} = scc_{res_i + n + m}\) 數量即為答案。

submisionn

參考文獻

哈哈人生 P9869-NOIP2023-B-三值邏輯

AugustLight P9869 [NOIP2023] 三值邏輯 題解

_yjh P9869 [NOIP2023] 三值邏輯 題解

SnowTrace NOIP2023 tribool

CountingGroup cnblogs

相關文章