1. 程式人生 > 其它 >2021-08-02新高二一期暑假集訓7

2021-08-02新高二一期暑假集訓7

D

標籤

\(dp\)​ + \(lgv\)​ 引理 + 計數

思路

求從 \((1, 1)\)​ 到 \((n, n)\)​ 不相交,可以轉化為 \(A\)​ 從 \((1,2)\)​ 到 \((n - 1, n)\)​ , \(B\)​ 從 \((2, 1)\)​ 到 \((n, n - 1)\),路徑不相交。 因為只有這樣,才能使兩人除起點和終點外路徑不相交。

\(lgv\)​​ 引理可解.

Code

總結

兩個人從 \((1, 1)\)\((n, n)\) 可以考慮轉化成 \((1,2)\), \((2, 1)\)\((n - 1, n)\) , \((n, n - 1)\)

​​​ ,這樣做可以去除兩個人起點和終點相同的影響

C

標籤

狀壓 \(dp\)

思路

由於 \(n\)​ 很小,所以考慮狀壓,設 \(f[i]\)​ 表示集合 \(i\)​ 中的罪犯已經被分配, \(cnt[i]\) 表示集合 \(i\) 中罪犯的矛盾數。

那麼有 \(f[i] = f[j] + 1 (cnt[i \ xor \ j] \leq k \land j 是 i 的子集)\)​​

複雜度為 \(O(3^n)\)

Code

總結

for (int j = i; j; j = i & (j - 1)) 可以總共 \(O(3^n)\)​​​​ 對每個集合列舉子集

B

標籤

連結串列

思路

求每個區間第 \(k\)​​ 小的和, 可以轉化為對於每個數,求它在多少個區間中是第 \(k\)​​ 小,把所有數從小到大排序,處理完一個數後把它刪除,其它數的下標不變,這樣可以保證序列中的所有數大於等於當前數。只需要從左邊找 \(i\) 個數,右邊找 \(k - i - 1\)​ 個數, 那麼在這些數中當前數一定是第 \(k\)​ 小。只要列舉 \(i\)​​ 就可以了。刪除操作可以用連結串列.

Code

總結

求每個區間具有某個性質的數的和,可以對於每個數求一下它產生多少次貢獻。

和第 \(k\) 小有關的題,求每一個數的貢獻,可以先把所有數從小到大排序,處理完一個數後把它刪除。這樣可以保證序列中的所有數大於等於當前數

A

標籤

性質 + 卡常

思路

性質

對於一棵樹,它可以分成幾個大小為 \(d\) 的聯通塊,當且僅當滿足以下條件.

  1. \(d|n\)
  2. \(\frac{n}{d}\)​​ 個子樹滿足大小為 \(d\)​ 的倍數.

充要性和必要性都顯然. 因為每分出一個聯通塊,一定會減少一棵大小為 \(d\)​ 的子樹,同時一些子樹的大小變成 \(d\)​ ,如果找不到大小為 \(d\)​ 的子樹,那麼就不滿足要求了.此時顯然不能保證有 \(\frac{n}{d}\)​ 個子樹滿足大小為 \(d\)​​​ 的倍數.因為一定有至少一個點是不能分到聯通塊中的.

列舉 \(d\) ,開一個桶 \(cnt_i\) 表示大小為 \(i\)​ 的子樹有多少個, 在 \(O(\frac{n}{d})\) 的時間內可以求出大小為 \(d\) 的子樹的個數.

總複雜度為 \((10 \times \sigma(n))\)​​,只有 \(70\)​​ 分. 因為被卡常了.

發現我們並不需要把樹真正的建出來,這樣可以省掉遞迴的常數,拿到 \(100\) 分。

Code

總結

有時候,如果只需維護一些簡單的資訊,尤其是隻從兒子向父親轉移,可以不用把樹真正建出來。這樣可以省掉遞迴的常數.