2021 年 NOIP 模擬賽隨便寫寫


博主是大鴿子,不定期更新。只要相信自己是鴿子,就可以心安理得地咕咕咕~

10.29

智商檢測題 \(\times 4\)

T1

排列形成若干環,求環數 \(\le k\) 的方案數。

直接 DP,\(f(i,k)\gets f(j,k-1)\times {i\choose j-1}\times (i-j-1)!\),然后拆開組合數可以前綴和優化,\(\mathcal O(nk)\)

后來發現就是個第一類斯特林數列前綴和。

T2

如果一個子串 \([l,r]\) 滿足 \(s_l=s_r\),那么其翻轉一定會被子串 \([l+1,r-1]\) 的翻轉表示。

T3

轉化到 \(4\) 個點的圖上,發現有很多邊重復。重邊中奇數條邊可以縮為一條,偶數條可以把最小邊拆出來縮為兩條(最小邊可能不走);子環縮為一條。

最多 \(16\) 條邊,就可以狀壓或者爆搜了。

T4

答案有單調性,先二分。然后貪心的去匹配,將所有人和卷軸排序,從左往右每個人一定是取最左端的若干卷軸,看是先往左走還是先往右走更優。


10.31

T1

可以線段樹模擬,區間加、區間賦值、區間求和。有點卡常。

更優秀的做法是,每次操作會刪去若干空格、產生一個空格,用一個棧模擬,同時記錄位置和空格長度來計算貢獻。

T2

對於每種結果對應的區間集合,我們再最小的區間統計貢獻。

補集轉化一下,求無貢獻的區間,充要條件為:左端點是區間最小值或者右端點是區間最大值。

單調棧可以求出滿足其中之一的。為了不算重兩者都滿足的,在統計后者的時候同時再維護一個單調棧,用來求某個區間內是區間最小值的左端點數。

T3

長為 \(b+1\) 的合法區間中有且僅有一個數出現兩次。

滑動這個區間,彈出的數若只出現一次,新加入的數只能與其相等;若出現兩次,新加入的數任意。

那么記錄重復的數的第一次出現次數,可以有 \(\mathcal O(n^2)\) 的 DP。

觀察 \(f(i,*)\to f(i+1,*)\) 的轉移過程,發現是整體平移和近似的全局加,用隊列和一個全局加標記模擬即可 \(\mathcal O(n)\)

T4

每次詢問都計算一遍,枚舉強制經過的邊統計方案數進行暴力容斥,沒啥思維水平。

有大量細節,大概是:不要算上大小為 \(2\) 的環;由於翻轉同構最后要 \(\div 2\);注意判出現環和所有邊構成一個環的情況。

復雜度 \(\mathcal O(m^22^m)\)


11.2

心情不好,不寫了口胡一下不寫代碼。

T1

后三個可以從低位到高位遞推。

第一個使用萬能的折半搜索。

T2

手推一下較小的情況,可以發現強的和強的內斗、弱的和弱的內斗更優。然后“我”的策略是盡量先打弱的。

若弱者有奇數個,挑一個和“我”打,其余兩兩配對;若弱者有偶數個,挑一個和“我”打,再挑一個和強的打(會產生兩個分支);強的和弱的其中有一個為 \(0\) 當然沒得選咯。

寫個記憶化搜索,每一層的強、弱者數量都只有兩種可能,狀態量是 \(\mathcal O(n)\) 的(有 \(2^n\) 個人)。

題解的 \(\mathcal O(n^2)\) 咋分析的?教教!

T3

美國數學競賽 ELMO2017 的一道題。

\(m\)\(1\) 的個數,出題人說一定可以把每一段的和控制在 \([m,2m)\) 之內,並且唯一的反例是 \(\texttt{11111}\)

那么可以做 \(\mathcal O(n^3)\) 的 DP。

出題人有個結論是:一定存在一種合法方案每一段長度不超過 \(4\)。證明就是 ELMO 的官方解析的事兒了,可以去問 @YCS_GG。口胡出題人過分了。

然后就 \(\mathcal O(n^2)\) 了,再用 \(\texttt{std::bitset<>}\) 優化就過了。

啥破題啊,擺一堆結論讓誰猜去啊。

T4

整出樹的歐拉序,每個狀態唯一對應歐拉序上的一個位置。每條邊只會被斷掉一次,每個活着的人一輪一定會斷掉一條邊。那么拿 splay 森林維護歐拉序,斷邊就是提取子樹,從歐拉序上提取區間,注意要刪去多出來的一個無用點。復雜度 \(\mathcal O(n\log n)\)

simple 的 idea,但是非常難寫。


11.3

T1

所有數都分解個質因數就完了。

T2

二分然后 \(\mathcal O(n^2)\) DP 出最少修改個數。

T3

CF280D,線段樹模擬費用流。

好像也可以用堆寫。

T4

每一位獨立,分開考慮,矩陣有結合律,線段樹。


11.6

T1

  • 做法 1

二分套樹狀數組上二分可以求出每個點作為中位數最大的能選的個數,每次詢問再二分一下最大的答案,復雜度 \(\mathcal O(n\log^2n)\),比較卡常。

  • 做法 2

\(\log\) 做法是基於選的數量從小到大,最大的中位數位置是單調不增的。邊單調移動指針邊 check,主席樹和樹狀數組均可。

T2

  • 做法 1

跑 Dijkstra,每次比較 \(\mathrm{dis}\) 時不顯示的記錄全部路徑,而是記錄更新它的前驅點 \(\mathrm{pre}\) 及倍增,以及路徑的哈希值。比較時先比較二進制串長度,長度相同時倍增到第一個不相同的位置進行比較。復雜度 \(\mathcal O(m\log^2 n)\)

注意要用 \(\texttt{std::multiset<>}\) 代替堆,避免堆中無用點的影響。而且還需要卡卡常數。

  • 做法 2

正解是分層 BFS,每次取出所有距離相同的點,先更新 \(0\) 邊,再更新 \(1\) 邊,復雜度 \(\mathcal O(n+m)\)

T3

假期望,計數帶權方案數。

  • 做法 1

考慮一個序列應當在何處被計算貢獻。將序列從小到大排序,前綴和,若一個點的前綴和 \(\le m\),就計算一次。

那么枚舉每個點作為被計算的點,為了不算重,欽定右面的排序后都在它前面,並且一邊是 \(f\) 一邊是 \(s\)

\[\sum_{v=1}^A\sum_{i=0}^{n-1}\sum_{j=0}^{m-v}f(i,v-1,j)\times s(n-i-1,v,m-j-v) \]

其中 \(f(i,j,k)\) 表示 \(i\) 個數,其中所有 \(\le j\) 的數和為 \(k\) 的方案數,\(s(i,j,k)=\sum_{l=0}^kf(i,j,l)\),可以直接 DP。

復雜度 \(\mathcal O(nm^2)\)

  • 做法 2

考慮直接枚舉最大的被選的數,和選了多少次,序列分成三部分進行多重集排列,

\[\sum_{v=1}^A\sum_{i=0}^{n-1}\sum_{j=1}^{n-i}h(i,j-1,m-j\times v){n\choose i}\sum_{k=j}^{n-i}{n-i\choose k}(A-v)^{n-i-k} \]

其中 \(h(i,j,k)\) 表示 \(i\)\(\le j\) 的數和為 \(k\) 的序列方案數。

發現我們不需要乘權值 \((i+k)\),因為這樣本身是會算重的,一個序列會在每個被選的權值算上被選個數次。

計算 \(h\) 同樣可以直接 DP,或者枚舉哪些數超過 \(j\) 進行容斥:

\[h(i,j,k)=\sum_{l=0}^i(-1)^l{i\choose l}{k-l\times j\choose i} \]

單點計算 \(h\)\(\mathcal O(n)\) 的,枚舉 \(v,j\) 是調和級數,總復雜度 \(\mathcal O(nm\log m+n^2m)\)

T4

先給 \(T_2\) 枚舉一個根,然后在 \(T_1\) 狀壓 DP。最后還要除掉 \(T_2\) 自同構的方案數。實現復雜度 \(\mathcal O(nm^22^m)\) 或者 \(\mathcal O(nm^23^m)\)


11.6

T1

狀態里記錄 \(\mathrm{cnt}_0(i)-\mathrm{cnt}_1(i)\) 的最大值和最小值與當前值的差,隨便 DP 一下。

T2

把車上的人的目的地都壓進狀態里。

一個性質是,如果某一時刻有一個上車,車上達到 \(4\) 個人,那么去下一個上車點之前只能先去往某個目的地。所以只需要記 \(3\) 個人的狀態。

以每次到達一個上車點為一個時間點,逐個人轉移,也不需要記當前的位置。

細節很多。

T3

折半。

T4

flow?咕咕咕。


11.7

T1

難點在於看懂題,樹上隨便搞搞。

T2

線代 nb 題,太難了不會。

T3

推式子 nb 題,太難了不會。

T4

最小樹形圖?直接上 tarjan 也是可以做的,可以用暴力代替可並堆,\(\mathcal O(n^2)\)

有更為優美的 DP 做法。首先只關注每個點最小的入邊,形成若干基環樹。

如果占領了基環樹環上的某一點,整個基環樹的每個點也就通過最小入邊被占領;如果占領非環上的點,其子樹內的點也是跟隨其通過最小入邊被占領。

所以最優占領順序是分段的,其中每一段是一棵子樹或基環樹。並且一個子樹/基環樹的占領后對其他點的影響取決於編號最大的點。

由於題目保證了除最小入邊以外有 \(t_{i,j}\ge t_{i,j+1}\),發現如果某一時刻 \(n\) 點被占領了,此時所有未被占領的基環樹一定是由 \(n\) 點占領環上某一點。

考慮怎么排列 \(n\) 點之前的占領順序,性質是:設 \(\mathrm{maxid}(u)\) 表示 \(u\) 子樹/基環樹內編號最大的點,\(n\) 點之前占領的每一段的 \(\mathrm{maxid}(u)\) 是單調遞增的。證明,如果存在相鄰兩段 \(u,v\) 滿足 \(\mathrm{maxid}(u)>\mathrm{maxid}(v)\) 那么將 \(v\) 調整至 \(n\) 點之后被占領,答案只可能更優。

這樣直接 DP 是 \(\mathcal O(n^2)\) 的。


11.8

T1

兩個等差數列的交也是等差數列,公差為 \(\mathrm{lcm}(d_a,d_b)\),可以第一個交點可以暴力找,因為范圍大概也是 \(\mathcal O(\mathrm{lcm}(d_a,d_b))\) 的。

邊角細節懶得想,只能靠對拍咯。

T2

最優策略一定是,每次先把頭盡量往右挪,然后把所有腿盡量往右挪。

T3

同余最短路,只要點按數字位數從小到大、出邊按 \(0\dots k-1\) 的順序更新,跑 BFS,就是最優的。

記不下答案,需要記錄轉移前驅點。

T4

\(A_x\) 集合的操作可以用帶權並查集維護,\(B_x\) 也是在並查集上記錄時間戳。

\(B_x\)\(A_x\) 有影響,但是每個點只有最后一次的賦值操作是有用的。離線下來處理每次詢問點的最近一次賦值操作,然后拆成兩次詢問解決。

復雜度 \(\mathcal O(m\log n)\)


11.10

T1

答案是 \(s,t\) 最短路,然后就顯然辣。

T2

散了吧散了吧,要生成函數的。

T3

排序后,選取子序列合法只需要保證相鄰兩項異或值 \(\ge x\),證明只要討論一下最高的不同位。

然后 01 trie 優化一下。

T4

這個容斥真的康不懂啊。 什么嘛,這個 T4 比 T2 陽間多了。

首先可以轉化一下,操作 \(k\) 次能夠得到的排列的條件為,最長上升子段的長度 \(\ge n-k\)

那么求最長上升子段的長度 \(\le n-k\) 的排列數,考慮容斥,即總排列數 - 欽定 \(1\) 個長為 \(n-k\) 上升子段的排列數 + 欽定 \(2\) 個長為 \(n-k\) 上升子段的排列數……

欽定的上升子段可能會相交,需要合並。“合並”的意思大概是,一個長為 \(n-k+2\) 的上升子段,可以是欽定了的兩個 \(n-k\) 的上升子段相交產生的,也可以是欽定了的三個 \(n-k\) 的上升子段相交產生的。那么這個 \(n-k+2\) 的子段的容斥系數應當是欽定 \(2\) 段的容斥系數與欽定 \(3\) 段的容斥系數之和。

根據合並的性質,這個容斥系數(設為 \(f_i\))可以 DP,\(f_1=1,f_{n-k}=-1\),然后有

\[f_i=-1\times \sum_{j=1}^{n-k-1}f_{i-j} \]

然后做 \(\mathcal O(n^2)\) 的 DP 來將若干上升子段拼接出一個排列,在 DP 時同時計算多重集排列 \(\frac{n!}{\prod a_i!}\) 的分母,設為 \(g_i\)

\[g_i=\sum_{j=1}^i g_{i-j}\times f_j\times \frac{1}{j!} \]

復雜度可以做到 \(\mathcal O(n^3)\) 了。

進一步觀察,\(f_i\) 的值非常稀疏,有值的地方只有

  • \(f_{(n-k)\times t}=-1\)
  • \(f_{(n-k)\times t+1}=1\)

只考慮這些地方,復雜度就是 \(\mathcal O(n^2\ln n)\) 啦。


11.13

XJ 公開賽。

T1

不考慮最小化次數,能刷盡量刷,求出每個位置開頭刷的高度,就可以求出每個位置最終被刷的高度,兩遍單調隊列。

每個連續段貪心即可最小化次數。

T2

\(i\) 個數能被異或上的數,是第 \(1\dots i-1\) 個數構成的線性基所能表示的所有數。

T3

記狀態 \((u,d,k)\) 表示到 \(u\) 點步數為 \(d\) 乘積為 \(k\)。每個點有用的狀態數不多,至多 \(500\),我也不知道為啥。題解說是類似整除分塊,是根號級別的。

那么直接做 SPFA,每次只保留乘積超過當前最大值的狀態,即可保證無冗余狀態。

T4

首先因為操作是可逆的,將 \(a,b\) 序列都排序。

\(l=r-1\) 時操作可以交換相鄰兩數;

\(\lfloor\frac{r-l+1}{2}\rfloor\) 次操作可以 reverse 一個有序區間;

兩個相鄰的有序序列 \(a_{1\dots n},b_{1\dots m}\) 滿足 \(a_i>b_j\),可以通過三次 reverse 排序。

發現這個操作次數的規模大約是讓我們歸並排序。

歸並兩段相鄰有序序列 \([l,\mathrm{mid}],[\mathrm{mid}+1,r]\),可以找到 \(x,y\) 使得 \(l\dots x\)\(\mathrm{mid}+1\dots y\) 是最小的 \(\frac{r-l+1}{2}\) 個數,那么排序 \(x+1\dots y\) 可以讓最小的 \(\frac{r-l+1}{2}\) 個數都移動到左側。然后遞歸處理。

操作次數是 \(\mathcal O(n\log^2n)\) 的。

題解說 \(n=4000\) 隨機數據期望下可以卡進 \(300000\) 的限制。

兩個相鄰的有序序列排序的操作次數是 \(\mathrm{len}-x+y\) 的,期望下是 \(1\)\(\mathrm{len}\) 的,最壞 \(2\)\(\mathrm{len}\)。然而將序列排序為正序和倒序是對稱的,兩者在此處的操作次數之和是 \(2\times \mathrm{len}\),都做一遍取較小的可以穩定通過。


11.15

T1

二分最大的絕對值,求個數的話雙指針。

T2

bfs 預處理,狀壓禮物集合。

T3

對於點 \(u\) 的一個祖先 \(x\)\(x\) 能被 \(u\) 得到的條件為,\(x\) 子樹內所有深度小於 \(\mathrm{dep}_u\) 的點動物均未參加。

按深度分組,從小到大處理,每個點要記錄子樹乘積,樹剖維護鏈乘、鏈求和。

T4

我已經聽三個 ez 學長講過了,模擬賽你還考。


11.16

賽時,一題不會,爆零了。

看題解改題,還是一題不會,咕了。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM