Chayas - 2023-2024 ICPC, Asia Yokohama Regional Contest 2023, Problem E

nkxjlym發表於2024-10-03

n(24)位的排列,有m個形如 \((a_i,b_i,c_i)\) 的限制,要求排列中 \(b_i\) 需要出現在 \(a_i\)\(c_i\) 之間,求滿足條件排列個數。
由 n 的範圍想到狀壓 dp。dp 排列的方式有很多種,如果是多項式級別的話可能是按順序填數列舉當前填的數在已經填入的數中的 rank。這道題是狀壓,有兩種可能:狀壓已經填入的格子按順序填數,或狀壓已經填入的數按順序填入格子。由於限制是在具體的數和相對位置上的,用後者比較合適。

直接 dp,暴力判斷當前狀態可不可以加入一個數 x。對於一個限制 (a,b,c),它對於狀態的限制可以只在加入 b 時考慮,即無條件加入 a 和 c,只在加入 b 的時候看違不違背 (a,b,c)。具體來說,往當前集合 S 加入 b 時,如果 a c 同時 (在/不在) S 中,則不合法,容易證明這等價於每加入一個 a/b/c 就考慮限制 (a,b,c)。這樣是 \(O(n^32^n)\) 的。(比較難卡,實現的好可以暴打標算)

法一:正攻,考慮對每一個 b 預處理出哪些 S 加入 b 時合法。即 S 中只存在 a 不存在 c 或 只存在 c 不存在 a。我們把中間為 b 的所有限制 \((a_i,b,c_i)\) 拿出來,可以看到會有若干個 \(a_i\)\(c_i\)\(b\) 的兩邊的要求。考慮到兩個限制之間存在相同的 a/c 會相關聯,將 \(a_i\)\(c_i\) 連邊建圖,一個連通圖裡應該滿足是個二分圖,且兩個連通圖間互不影響。二分圖內同屬一邊的點也同在 b 的一邊,所以我們可以得到若干個集合對 \((U_i,V_i)\),表示集合 \(U_i\) 必須同在 b 的一邊並且 \(V_i\) 同在另一邊,不同的集合對相互獨立。回頭考慮合法的 S,這個 S 可以看作是 b 的左邊的所有點,所以它應該可以由每對 \((U_i,V_i)\) 選一個集合全部並起來得到。對於每個 b,獲取 \((U_i,V_i)\) 並列舉所能生成的所有的 S,這是 \(O(n2^n)\) 的。實際上,忽略那些與 b 無關的數,每個二分圖至少有兩個點,最多隻有 \(\frac{n}{2}\) 個集合對,可以最佳化到 \(O(n2^{\frac{n}{2}})\)。最終的複雜度還是取決於 dp 複雜度,是 \(O(n2^n)\)

法二:正難則反,考慮對每一個 b 預處理出哪些 S 加入 b 時不合法。這樣之所以會更簡單是因為一旦 S 中的一個子結構違背了某個 (a,b,c),那麼不管其他位的狀態如何,S 始終是不合法的。與合法時必須要求對所有 (a,b,c) 合法不同,不合法只需要對某個 (a,b,c) 不合法即可,不需要考慮包含 b 的所有 \((a_i,b,c_i)\) 的整體結構。具體來說,對每個 (a,b,c) 所有 a c 對應位同為 0 與同為 1 的 S 都應被標記為不合法。這很容易用高維字首和解決。如果對每個 b 做字首和是 \(O(n^22^n)\),但我們可以把字首和的陣列設定為狀態 S 對哪些 b 不合法,這樣只需要一次字首和 \(O(n2^n)\)。這個演算法不如法一快是因為高維字首和與 dp 都是 \(O(n2^n)\) 的,相當於一個兩倍常數。

法三:重新考慮集合合法性的問題。我們之前提到對於 (a,b,c),同時存在 a c 則無法加入 b。但事實上,同時存在 a c 本就是不合法狀態,可以在加入 b 之前就判斷其不合法。於是我們可以轉變思路,考慮 S 狀態本身是否合法。延續法二的思路,還是考慮不合法的 S,由於這次我們沒有欽定 b,某個 (a,b,c) 會對 S 裡對應的三位有限制。S 對於 (a,b,c) 不合法等價於 \(S_a=S_c=1,S_b=0\)\(S_a=S_c=0,S_b=1\),這個可以用帶容斥的高維字首和解決,複雜度 \(O(n2^n)\)。類似的,這個做法也跑的比法一慢。

注:法二和法三遇到的是同一類問題,即給定集合 \(A=\{a_0,a_1,\cdots,a_p\}\)\(B=\{b_0,b_1,\cdots,b_q\}\),欽定二進位制表示的集合 S 中的 \(S_{a_i} = 0\)\(S_{b_i}=1\),其他位可以為 0 也可為 1,並對於所有滿足條件的 S,做操作 \(f_S+=c\)。如果 B 是空集,就可以轉化為對所有 \(S\sube U\backslash A\) 做上述操作,如果 A 是空集,可以轉化為對所有 \(S\supe B\) 做上述操作。如果兩個集合都有元素,則可以先假設其中一個為空集,然後容斥掉多操作的部分。不過值得注意的是,法二中的操作不是加等於而是或等於,這導致無法容斥,但具體需求正好滿足可以分為兩部分來做,其中每一個部分都是有一個集合是空集的問題,剛好不需要容斥。

相關文章