2019各省省選試題選做


2019各省省選試題選做

2019.05.09
把拖了幾天的SDOI Day2更了。姑且算是完結撒花?

省份 Day1T1 Day1T2 Day1T3 Day2T1 Day2T2 Day2T3
ZJOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
HNOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
十二省 \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
GX/GZOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
BJOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
SNOI \(\surd\) \(\surd\) \(\surd\) \(\surd\)
JSOI \(\surd\) \(\surd\) \(\surd\) \(N/A\) \(N/A\) \(N/A\)
TJOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)
SDOI \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\) \(\surd\)

ZJOI

Day1T1 麻將

先考慮一個這樣的問題:給定一副麻將問其是否存在一個子集能胡。兩種牌型中七對子很好處理,只需要記有多少種數值出現了大於等於\(2\)次就行了。
考慮用\(dp\)去判定是否能按第一種牌型胡。\(f_{i,0/1,j,k}\)表示從小往大考慮了\(1...i\)的面值,前面是否選了對子,選了\(j\)\(i-1,i,i+1\)順子,\(k\)\(i,i+1,i+2\)順子,最多能湊出的面子數(由於\(i+1\)尚未確定,因而\(j,k\)並不會被計入面子數)。轉移時根據\(i+1\)的數量,枚舉\(i+1,i+2,i+3\)順子的數量,剩下的\(i+1\)組成刻子。
再考慮原題目中的權值期望怎么轉化。顯然這個期望可以拆成“在手上有\(i(i\ge13)\)張牌時檢查是否胡牌,若不胡則貢獻\(+1\)”,因此我們考慮求出有\(i\)張牌時仍不胡的方案數,乘上\((4n-i)!\)后相加即可得到總答案。
回到原問題。在原問題中我們仍考慮按面值從小到大加入麻將牌,並將上述判定胡牌的\(dp\)數組作為狀態壓進當前\(dp\)中。經搜索發現本質不同的狀態只有\(S=3956\)種,本質不同的不胡狀態只有\(S_0=2091\)種,因而可以設\(dp_{i,j,k}\)表示考慮\(1...i\)的面值,當前狀態為\(j\),選了\(k\)張牌的方案數,轉移只要枚舉\(i+1\)面值選多少張,方案數乘個組合數即可。總復雜度為\(O(n^2S_0)\)
code

Day1T2 線段樹

可以發現操作的意義等價於,每次以\(\frac 12\)的概率進行一次區間覆蓋操作,求線段樹上有標記節點的期望個數。根據期望的線性性,只需要求出每個節點有標記的概率\(f_i\)再求和即可。
為了方便的維護這個概率,我們需要額外對線段樹上每個點維護該點到根的路徑上有標記的概率\(g_i\)。每次修改都會有\(O(\log n)\)個節點的\(f_i\)值變成\(\frac{f_i}{2}\)\(\frac{f_i+1}{2}\)\(\frac{f_i+g_i}{2}\)中的一種(請根據實際含義自行理解),而同時也會有\(O(\log n)\)棵線段樹子樹內的\(g_i\)值變成\(\frac{g_i+1}{2}\)
在具體實現中,可以維護\(g_i'=1-g_i\),這樣對子樹內\(g_i'\)的修改就變成了\(g_i'\gets \frac{g_i'}{2}\),直接打區間乘法標記(或者直接記區間要除幾次\(2\))即可。
code

Day1T3 Minimax搜索

考慮對每個\(R\)求出\(ans_R\)表示有多少個葉子集合滿足權值\(\le R\),差分即可得到答案。設樹上共有\(k\)個葉子節點,易知\(ans_n=2^k-1\)

由於我們只需要改變\(w\)的值,而變成的值的可行域顯然是連續的,所以我們只需要嘗試着將這個值改為\(w+1\)\(w-1\)即可。

如果可修改集合包含\(w\)那么其權值一定為\(1\)(只要把\(w\)改掉就萬事大吉了),因此\(ans_1=2^{k-1}\)

否則,如果想要把權值變成\(w+1\),那么大於\(w\)的點的權值顯然不會被修改,而小於\(w\)的點的權值會被盡量改成\(w+1\)(如果修改代價不超過\(R\)的話)。把權值變成\(w-1\)的過程同理。可以發現兩類修改互不影響,所以我們只要分別求出兩類操作下\(w\)沒有被改變的方案數,直接相乘得到的就是\(w\)沒有被改變的方案數。

\(f_i\)表示\(i\)點權值\(\le w\)的概率(設概率而非方案數可以方便轉移),這樣奇數深度的轉移為\(f_u=\prod f_v\),偶數層的轉移為\(f_u=1-\prod(1-f_v)\)。同理,設\(g_i\)表示\(i\)點權值\(< w\)的概率,轉移與\(f\)的轉移完全一致。注意在這里\(f_i\)只考慮所有\(<w\)的葉子,\(g_i\)只考慮所有\(>w\)的葉子。

由此在\(R\)確定的情況下我們可以通過一遍樹形\(dp\)求出\(ans_R=2^{k-1}(1-f_1(1-g_1))+2^{k-1}\)。這樣我們就得到了一個\(O(n(R-L+1))\)的做法,可以獲得\(70\)分。

滿分做法其實很顯然。\(R\)\(2\)\(n-1\)移動時每次只會改變至多兩個葉子的\(dp\)值,因此使用動態\(dp\)實現即可,復雜度\(O(n\log^2n)\),可以獲得\(100\)分。

在具體實現中,由於深度奇偶性不同導致轉移不同,故可以令\(f_i'=[\mbox{i點深度為奇數}]f_i+[\mbox{i點深度為偶數}](1-f_i)\),這樣轉移就可以統一為\(f_u'=\prod(1-f_v')\)

此外在動態\(dp\)的過程中可能會出現乘\(0\)后除\(0\)的問題,需要開一個\(pair\)記錄\(dp\)值非零部分的乘積以及乘\(0\)的個數,從而實現信息可減。

code

Day2T1 開關

先求出\(n\)次操作后使開關狀態合法的方案數,其對應的指數型生成函數為(記\(P=\sum_{i=1}^np_i\))$$F(x)=\prod_{i=1}^n\frac{e^{\frac{p_ix}{P}}+(-1)^{s_i}e^{-\frac{p_ix}{P}}}{2}$$

然而這個方案數包含了一些多次達到合法狀態的方案,需要將其排除。考慮\(n\)次操作后回到原狀態的方案數對應的指數型生成函數:

\[G(x)=\prod_{i=1}^n\frac{e^{\frac{p_ix}{P}}+e^{-\frac{p_ix}{P}}}{2} \]

在具體實現中,只需要記錄\(F(x)=\sum_{i=-P}^Pa_ie^{\frac{ix}{P}}\)中的\(a_i\)系數即可,\(G(x)\)同理。這一部分暴力實現的話復雜度為\(O(nP)\)

再記\(H(x)\)為答案的生成函數,令\(F(x),G(x),H(x)\)對應的普通生成函數分別為\(f(x),g(x),h(x)\),可知\(g(x)h(x)=f(x)\)

(原本這里誤寫成了\(G(x)H(x)=F(x)\),實際上由於答案是操作序列的一段前綴,因此\(g\)\(h\)的關系應當為直接拼接而非組合相乘,對應的也應為普通生成函數的乘法。感謝@leoiter指正。)

關於指數型生成函數與普通生成函數的轉化:當\(F(x)=\sum_{i=-P}^Pa_ie^{\frac{ix}{P}}\)時,\(f(x)=\sum_{i=-P}^P\frac{a_i}{1-\frac{ix}{P}}\)

此時要求的答案為\(h'(1)\),使用公式\((\frac{f(x)}{g(x)})'=\frac{f'(x)g(x)-f(x)g'(x)}{g^2(x)}\)計算答案。但是\(x=1\)代入\(f(x)\)\(g(x)\)后函數不收斂。考慮將\(f(x)\)\(g(x)\)同乘上\(\prod_i(1-\frac{ix}{P})\)結果不變,此時\(f(x)=\sum_ia_i\prod_{j\neq i}(1-\frac{jx}{P})\),可以計算出\(f(1)=a_P\prod_{i\neq P}(1-\frac{i}{P})\)\(f'(1)=-(\prod_{i\neq P}(1-\frac{i}{P}))(\sum_{i\neq P}\frac{a_i}{1-\frac{i}{P}}+a_P\sum_{i\neq P}\frac{\frac{i}{P}}{1-\frac{i}{P}})\)

(以上默認\(i,j\in[-P,P]\cap\mathbb{Z}\)

推導過程中可能需要用到的東西:\((\prod_i(1+a_ix))'=\sum_ia_i\prod_{j\neq i}(1+a_jx)\)

\(g(x)\)的對應系數為\(b_i\),不難發現實際上\(a_P=b_P=\frac{1}{2^n}\),因而可以簡化一些運算,最終的答案為\(2^n\sum_{i\neq P}\frac{b_i-a_i}{1-\frac{i}{P}}\)

code

Day2T2 語言

對每個點求所有覆蓋該點的鏈的鏈並大小,加起來除以\(2\)就是答案。

樹上差分,即對於鏈\((x,y)\)\(x\)\(y\)處加入這兩個點,在\(fa_{lca(x,y)}\)處刪去(注意判出現次數)。線段樹合並即可,復雜度\(O(n\log n)\)

code

Day2T3 浙江省選

顯然每個人就是一條直線。對所有人求個半平面交(簡易版,因為斜率均為正),然后那些在半平面邊界上(包括一個整點)的人可以拿第一名。

接着考慮剩下的人。如果剩下的某個人想要拿第二名,那么他至少要在剩下的人中拿第一。對剩下的所有人做半平面交,得到的就是所有第二名的候選人,接着拿所有第一名在這個半平面上二分求出他會讓哪段\(x\)坐標范圍的名次\(+1\),即做一次區間覆蓋。當半平面邊界上的某人只被不超過\(1\)個人覆蓋時,他就可以拿到第二名。

第三名至第\(m\)名依此類推,只需要做\(m\)次半平面交+二分即可,復雜度\(O(mn\log n)\)

實現上有些小細節,具體可以參照代碼。code

HNOI

link

十二省聯考

Day1T1 異或粽子

把所有右端點丟到堆里,每次取出最大的即可,需要實現可持久化\(Trie\)樹上求異或第\(k\)大。復雜度\(O(n\log a_i+k\log n+k\log a_i)\)
code

Day1T2 字符串問題

\(A_x\)向所有它支配的\(B_y\)連邊,而\(B_i\)向所有以它為前綴的\(A_j\)連邊。上述方式建圖后,最終答案記為圖中以\(A\)串長度為權值的最長路。

直接暴力建邊的邊數是\(O(n^2)\)級別的,顯然難以承受。考慮優化這個建邊過程。

\(SAM\)后從上往下連邊就行啦,注意同一個節點內的所有串要按照長度排序(長度相同時\(B\)串要排在\(A\)串的前面)后串成一條鏈。這樣建圖的總點數不超過\(2n_a+n_b+SAM\)節點數。

此外:

數據千萬條,清空第一條。

多測不清空,爆零兩行淚。

code

Day1T3 騙分過樣例

我一定是閑得發慌才去寫這種題的\(Q\omega Q\)
\(5\)個點是輸入\(x\)\(19^x\%p\)\(x\)的范圍比較大(超過long long的值域范圍)所以直接讀入字符串后十進制快速冪就行了。\(4,5\)兩個點需要自己猜模數。
\(6,7\)兩個點是爆int的錯誤示例。並不能快速冪,不過通過各種途徑可以發現循環節不長,所以直接把循環節打出來就好了。
\(8,9,10\)是區間求質數。直接大力\(\mbox{Miller_Rabin}\)即可。
\(11,12,13\)是區間求\(\mu\)。可以先分解三次根號\((10^6)\)范圍內的質因子,然后最多最會剩下\(2\)個質因子,先判斷是否相等(完全平方數),再\(\mbox{Miller_Rabin}\)判斷其是否是質數即可。這部分跑得比較慢,因此面向數據卡了波常,代碼中所有難以理解的部分均為卡常的跡象。
\(14,15,16\)區間求原根。設\(p-1\)\(k\)種不同質因子,那么存在一種\(O(nk\log p)\)的判斷方法,同時也存在一種\(O(pk)\)的方法。兩者結合就行了。
code

Day2T1 皮配

在沒有任何城市限制與偏好限制的情況下,對一個人數為\(s\)的學校定義其二元生成函數\(1+x^s+y^s+x^sy^s\)。將所有學校的生成函數\(\prod\)起來,由於總人數已知,所以\(C_0,C_1,D_0,D_1\)等價於對\(x\)\(y\)的指數做了一定的范圍限制(在某個\([l,r]\)之間)。

對於一座沒有任何偏好的城市,設其學校人數集合為\(S\),則其生成函數為\((1+y^{sum(S)})\prod_{s\in S}(1+x^s)=\prod_{s\in S}(1+x^s)+y^{sum(S)}\prod_{s\in S}(1+x^s)\)。若存在一些學校存在偏好,則該學校對應在\(1\)\(y^{sum(S)}\)中的\(1\)\(x^s\)項要被刪去,而這並不會影響到其余沒有偏好的學校(因為對於其余的學校你仍可以提一個\((1+x^s)\)項出去),而所有無關的項中\(x\)\(y\)相對獨立,所以可以先分別\(O(nm)\)地計算沒有偏好的學校及城市的生成函數,再\(O(km^2)\)地暴力\(dp\)存在偏好的學校的生成函數。由於限制了單所學校的人數上限,所以實際上復雜度只有\(O(k^2ms_i)\)

code

Day2T2 春節十二響

根節點顯然自成一組,所以只需要考慮合並根的若干子樹。顯然最優策略會是:兩棵子樹內最大值分在一組,次大值分在一組......可以通過數學歸納證明一定不存在更優操作。

由於需要支持動態插入(根節點),因此考慮使用堆來維護子樹內的決策。使用長鏈剖分,每次計算時先\(O(1)\)繼承長兒子,再暴力地合並其余兒子,復雜度可以做到\(O(n\log n)\)

使用priority_queue::swap可以做到\(O(1)\)交換兩個堆。

(其實std::swap復雜度也是\(O(1)\)的,感謝@EndSaH指正。)

code

Day2T3 希望

枚舉一個點,求所有救援隊都覆蓋其的方案數,但這樣顯然算重了,因此需要容斥。考慮一種方案下能被每個救援隊都覆蓋的點一定是一個連通塊,其點數\(-\)邊數\(=1\),因此我們只需要對每個點求答案,再對每條邊求答案就行了。具體的,設\(f_{i,j}\)表示\(i\)點子樹中距離\(i\)不超過\(j\)的連通塊個數,\(g_{i,j}\)表示\(i\)點子樹外距離\(i\)不超過\(j\)的連通塊個數,轉移如下:

\[f_{i,j}=\prod_{v \in son(i)}(f_{v,j-1}+1) \]

\[g_{i,j}=g_{fa_i,j-1}\prod_{v\in son(fa_i)}(f_{v,j-2}+1)+1 \]

這樣的時空復雜度均為\(O(nL)\)code

考慮優化。
首先\(f\)的轉移可以長鏈剖分。在長剖的過程中,每當暴力合並一個輕兒子后,都需要將長鏈的一段后綴乘上一個定值,可以轉為前綴乘上其逆元,這樣暴力掃前綴復雜度才是對的。由於后綴乘上的值可能是\(0\)不存在逆元,因而需要額外開兩個變量記錄一段后綴的值變成了多少。

\(g\)的轉移需要分輕重兒子分別考慮。首先可以發現的是,若\(i\)點距離子樹內最深點長度為\(d\),則\(g_i\)中只有狀態\(g_{i,L-d...L}\)是有用的,也就是說\(g_i\)需要保存的長度也只有\(i\)點子樹內最深深度那么長。對於所有輕兒子,只需要記錄前后綴的信息即可,具體來說可以對\(f\)實現可回退化,求\(g\)的時候倒着訪問所有兒子,這樣每次對\(f\)的操作回滾即可得到前綴信息,同時邊做邊維護后綴信息即可。重兒子直接暴力掃一遍最終維護出的后綴信息即可,復雜度為最長輕兒子長度。

由於涉及到求逆元復雜度仍然是\(O(n\log mod)\),不過可以發現每次需要求逆的東西都是某個\(f_{i,L}\),而這個東西可以預處理\(dp\)一遍直接求出,因而可以做到離線\(O(n)\)\(n\)個數的逆元。

講道理這道題難點不在算法而是在實現吧,相信大家應該都知道怎么做,至於怎么寫出來那就得各憑本事了呢。

code

GX/GZOI

Day1T1 與或和

拆位考慮,假設所有數字都是\(0/1\)。一個子矩陣與為\(1\)當且僅當它全都是\(1\),或為\(1\)當且僅當存在至少一個\(1\),反過來就是沒有\(1\)。因此求全\(1\)\(0\)子矩形個數就好了,復雜度\(O(n^2\log a_i)\)
code

Day1T2 寶牌一大堆

(出這種題有意思嗎)
反正大力\(dp\)就好了吧,相信大家對於麻將形式的\(dp\)已經很熟悉了。
題中給出的\(15\)\(18\)張牌的和牌方案,其實等價於是用一個杠子代替了一個面子,因而可以統一為一種\(dp\),即\(f_{i,j,k,x,y}\)表示考慮了前\(i\)種牌,有\(j\)\(i-1\)開頭的順子,\(k\)\(i\)開頭的順子,已經出現了\(x\)個面子/杠子和\(y\)個對子情況下的最大分數,其中\(j,k\le2,x\le4,y\le1\)。此外就只剩下七對子和國士無雙兩個簡單\(dp\)了。
code

Day1T3 特技飛行

顯然強行二合一。第一問是給出平面上的若干點和\(k\)個關鍵點,每個關鍵點有個覆蓋范圍\(r\),可以覆蓋與其曼哈頓距離不超過\(r\)的所有點,求有多少個點會被至少一個關鍵點覆蓋。顯然曼哈頓轉切比雪夫(就是坐標軸旋轉\(45^\circ\))后覆蓋范圍就是個矩形,因此排序+掃描線可以做到\(\log n\)
第二問是求最多可以做多少次擦肩而過,因為顯然如果每次都做對向交換的話是一定合法的。這其實等價於是問最少做多少次對向交換。考慮全部做擦肩而過后在終點處得到的相對順序排列\(p\),每次的對向交換在最終的排列\(p\)上的作用體現即為交換了某兩個元素的位置。因為我們只需要用最小的交換次數將\(p\)還原成元排列即可。
code

Day2T1 逼死強迫症

\(f_{i,0/1/2}\),然后矩陣轉移即可。
code

Day2T2 旅行者

對每個點求出到達這個點最近的關鍵點\(f_i\)以及從這個點出發能到達的最近關鍵點\(g_i\),然后枚舉一條邊\(u\to v\),若\(f_u\neq g_v\)則可以用這條邊更新答案。
code

Day2T3 舊詞

權值差分后主席樹維護鏈並即可。當然也可以離線線段樹做到空間線性。
code

BJOI

Day1T1 奧術神杖

權值轉對數后相當於求權值的平均值,因此使用分數規划。對所有串建立\(AC\)自動機后\(dp\),復雜度\(O(ns\alpha\log\mbox{eps}^{-1})\),其中\(\alpha\)為字符集大小,\(\mbox{eps}\)為設定的精度范圍。
能過就行了。
code

Day1T2 勘破神機

第一個數列顯然就是\(f_1=1,f_2=2\)的斐波那契數列。第二個數列只有偶數項非零,單獨拿出來后有\(g_1=3,g_2=11,g_n=4g_{n-1}-g_{n-2}(n>2)\),可以打表找規律或強行\(BM\)oeis大法好

顯然兩者均為線性常系數齊次遞推式,可以根據其特征根解得其通項式。一般的,設其特征根為\(x_1,x_2(x_1\neq x_2)\),則通項式為\(f_n=c_1x_1^n+c_2x_2^n\)。特殊的,題中所給出的兩個數列的特征根以及對應系數分別為:

\[\begin{cases}x_1=\frac{1+\sqrt 5}{2}\\x_2=\frac{1-\sqrt5}{2}\\c_1=\frac{5+\sqrt 5}{10}\\c_2=\frac{5-\sqrt5}{10}\end{cases} \]

以及

\[\begin{cases}x_1=2+\sqrt3\\x_2=2-\sqrt3\\c_1=\frac{3+\sqrt3}{6}\\c_2=\frac{3-\sqrt3}{6}\end{cases} \]

接下來的推導均采用一般形式。
\(\binom nk\)可以被認為是一個關於\(n\)\(k\)次多項式,即\(\binom nk=\frac{1}{k!}\prod_{i=0}^{k-1}(n-i)\)
題目要求的是\(\sum_{i=1}^n\binom{f_i}{k}\),可以轉化為求\(\sum_{i=1}^nf_i^{1...k}\),因而只考慮怎么求\(\sum_{i=1}^nf_i^k\)

\[\sum_{i=1}^nf_i^k=\sum_{i=1}^n(c_1x_1^i+c_2x_2^i)^k\\=\sum_{i=1}^n\sum_{j=0}^k\binom kj(c_1x_1^i)^j(c_2x_2^i)^{k-j}\\=\sum_{i=1}^n\sum_{j=0}^k\binom kjc_1^jc_2^{k-j}(x_1^jx_2^{k-j})^i\\=\sum_{j=0}^k\binom kjc_1^jc_2^{k-j}\sum_{i=1}^n(x_1^jx_2^{k-j})^i \]

后面是個等比數列求和,特判下\(q=1\)的情況就好了。
總復雜度\(O(Tk^2\log n)\)。比較難受的一點是\(998244353\)下不存在\(3\)\(5\)的二次剩余,因而需要擴域,即使用一個\(pair(a,b)\)來表示\(a+b\sqrt 3\),其中\(a,b\in\mathbb{R}\)
code

Day2T1 排兵布陣

很顯然是個背包,每次只枚舉有用的轉移點,暴力轉移即可。
code

Day2T2 光線

對於兩面鏡子\((a_1,b_1)\)\((a_2,b_2)\),考慮將其合為一面鏡子\((\frac{a_1a_2}{1-b_1b_2},b_1+\frac{a_1^2b_2}{1-b_1b_2})\)
上面的式子其實很好推導,只需要枚舉光在兩鏡之間反射了多少次,即可得到一個等比數列求和的形式,化簡后即可得到上式。
把所有鏡子自下而上合並即可。
code

Day2T3 刪數

對於\(i\in[1,n]\),若數列中含有\(cnt_i\)\(i\),則進行對區間\([i-cnt_i+1,i]\)的區間覆蓋。最終的答案就是未被覆蓋部分的長度。
然后就只需要考慮如何維護這個東西了。區間覆蓋可以認為是區間\(+1\),計算答案時只需要數區間內最小值的個數即可(最小值不會小於\(0\))。由於存在值域平移的操作,因此在線段樹中只維護真實值范圍在\([1,n]\)的區間覆蓋就行了。復雜度\(O(n+m\log n)\)
code

SNOI

Day1T1 字符串

\(n=10^6\)時倍增求后綴數組大約要\(0.6\sec\)。(雖然也能過就是了)

其實需要用到的只有相鄰兩個后綴的\(lcp\),直接\(O(n)\)從后往前預處理即可。

接着來就是一個std::stable_sort的事情了。
code

Day1T2 數論

\(x\to (x+P)\%Q\)會形成\(\gcd(P,Q)\)個長度為\(\frac{Q}{\gcd(P,Q)}\)的環。

枚舉\(x\%P\)的值(即枚舉\(a_i\)),問題變成求有多少\(0\le x\le \lfloor\frac{T-1-a_i}{P}\rfloor\)滿足\((Px+a_i)\%Q\in\{b_i\}\)。其實就是求從某個點出發走若干步(\(\lfloor\frac{T-1-a_i}{P}\rfloor\)步)能到達的所有點的點權和。隨便討論一下即可。復雜度\(O(P+Q)\)
code

Day1T3 通信

費用流暴力建圖點數\(O(n)\)邊數\(O(n^2)\)
隨便分治一下可以將點數和邊數都變成\(O(n\log n)\)級別。然后...就能跑了?
code

Day2T1 紙牌

恭喜SN喜題第三道麻將題!不知道下一道將花落誰家呢?

直接\(9\times9\)大力矩乘即可,復雜度\(O(9^3X\log n)\),當然其實也可以做到\(O(9^2X\log n)\)
code

JSOI

T1 精准預測

以下用\((t,x)\)表示\(t\)時刻\(x\)這個人活着的狀態,\((t,\overline{x})\)表示\(t\)時刻\(x\)這個人死亡的狀態。

很顯然的\(\text{2-sat}\)建圖。對於第一種限制關系,連邊\((t,x)\to(t+1,\overline{y}),(t+1,y)\to(t,\overline{x})\)。對於第二種限制關系,連邊\((t,x)\to(t,\overline{y}),(t,y)\to(t,\overline{x})\)。此外還需要連邊\((t,\overline{x})\to(t+1,\overline{x}),(t+1,x)\to(t,x)\)

如此建圖后每個\(i\)的答案即為從\((T+1,i)\)出發不能到達的\((T+1,\overline{j})\)\(j\)的數量\((j\neq i)\)。當然還需要滿足\(i,j\)兩者有可能活下來,即\((T+1,i)\)無法到達\((T+1,\overline{i})\)\((T+1,j)\)無法到達\((T+1,\overline{j})\)

暴力建圖的點數為\(2n(T+1)\)。首先可以發現建出來的圖是一張\(\text{DAG}\),同時只有\(m\)條限制中被用到的點是有用的,其余很多點均只有一條連向上一時刻或者是下一時刻的出邊,可以減小圖的規模至\(2m+2n\)當然這並不是最優的,反正能過就行了。

問題轉化為求\(\text{DAG}\)上每個點出發能到達哪些關鍵點。這個問題目前只還能做到\(\text{bitset}\)復雜度,因此總時間復雜度\(O(\frac{nm}{\omega})\),看上去能過。

空間開不下?分多次做不就好了嗎。

code

T2 神經網絡

姑且算是個二合一。

第一問是對每棵樹求出將這棵樹划分成\(1...n\)條鏈的方案數。注意在這里鏈是有方向的,因此每選取一條長度大於\(1\)的鏈方案數就要乘\(2\)。這個可以用\(O(n^2)\)的樹\(dp\)解決。

第二問是求將所有樹划分的若干條鏈擺成一個環,要求相鄰不能同色(來自同一棵樹)的方案數。一個顯然的想法是容斥掉相鄰不同色,即強制若干對相鄰同色,容斥系數顯然應為\(\pm1\)

先假設擺成的不是環而是鏈,即不考慮首尾不同色也不考慮循環同構。考慮用指數型生成函數分配序列上的位置。對於一棵\(n\)個節點的樹,設將其划分成\(i\)條鏈的方案數是\(f_i\),那么其對應的指數型生成函數應為:

\[\sum_{i=1}^nf_ii!\sum_{j=1}^i(-1)^{i-j}\binom{i-1}{i-j}\frac{x^j}{j!} \]

然后考慮怎么拓展到環上。我們欽定一種顏色(一棵樹)作為環的開頭(即作為第一個元素),如果這種顏色被分了\(i\)段,那么這種方案在最終的答案里就會被算\(i\)次。因此我們將這種顏色的指數型生成函數設為:

\[\sum_{i=1}^nf_i(i-1)!\sum_{j=1}^i(-1)^{i-j}\binom{i-1}{i-j}\frac{x^{j-1}}{(j-1)!} \]

然而這樣沒有考慮首尾不同色。不過我們只需要減去強制首尾同色的方案就好了:

\[\sum_{i=2}^nf_i(i-1)!\sum_{j=2}^i(-1)^{i-j}\binom{i-1}{i-j}\frac{x^{j-2}}{(j-2)!} \]

上下兩個函數做差后得到的就是這種被欽定的顏色對應的指數型生成函數。

把所有函數(暴力地)卷起來即可得到答案。

code

T3 節日慶典

一個位置作為最小循環表示的起始位置的一個必要條件為以其為起始位置的后綴是一個最小后綴。如果做過這個題的話應該知道一個字符串的最小后綴只有至多\(\log n\)個,所以暴力維護出這個備選集合再比較就行了。

簡單證一下這個性質:考慮相鄰的兩個最小后綴\(i,j\),若\(|j|<|i|<2|j|\),則說明\(i=AAB,j=AB\),其中\(A,B\)均為字符串,且\(B\)\(A\)的一個嚴格前綴。此時考慮\(i=AAB,j=AB,k=B\),可以發現無論如何最小后綴都會在\(i\)\(k\)之間產生,\(j\)不可能成為最小后綴,由此說明相鄰兩個最小后綴之間一定至少相差\(1\)倍,因此數量不超過\(\log n\)

然而\(n\)的規模大得有些超越想象,傳統后綴數據結構可能難以勝任。可以考慮退而求其次,在\(O(n)\)的時間復雜度內求出原串的所有后綴與原串的\(lcp\)長度,即使用所謂的\(\text{Z-algorithm}\)。由於備選集合內的后綴一定存在前綴關系(較短串一定是較長串的前綴),因此比較時需要用到的也就只有每個后綴與原串的\(lcp\)了。

code

TJOI

Day1T1 甲苯先生的字符串

矩乘即可。
code

Day1T2 甲苯先生的滾榜

動態開點線段樹+樹狀數組維護即可。
code

Day1T3 唱、跳、rap 和籃球

由於非法串不可能相交,所以可以直接枚舉非法串至少出現多少次,剩下位置隨便填,容斥即可得到答案。設出現非法串出現至少\(i\)次的方案數是\(dp_i\),則答案為\(\sum_{i=0}^{min\{n/4,a,b,c,d\}}(-1)^i\binom{n-3i}{i}dp_i\)

考慮求\(dp_i\)。方案數顯然就是四個指數型生成函數卷起來,即\(dp_i=[\frac{x^{n-4i}}{(n-4i)!}](\sum_{i=0}^{a-i}\frac{x^i}{i!})(\sum_{i=0}^{b-i}\frac{x^i}{i!})(\sum_{i=0}^{c-i}\frac{x^i}{i!})(\sum_{i=0}^{d-i}\frac{x^i}{i!})\)。暴力計算復雜度\(O(n^3)\),可以考慮維護前兩個函數的乘積與后兩個函數的乘積,每次\(i\)改變時只需要\(O(n)\)即可修改兩個多項式,求多項式的某一項系數也可以直接\(O(n)\),總復雜度\(O(n^2)\)
code

Day2T1 大中鋒的游樂場

設狀態\((u,x\in[-k,k])\),最短路即可。
code

Day2T2 甲苯先生和大中鋒的字符串

\(\text{SAM}\)即可。
code

Day2T3 甲苯先生的線段樹

先求出路徑上所有點編號和\(n\)。設路徑深度最小的點為\(x\)

\(x\)為中點,枚舉左右兩側鏈的長度\(L,R\)\(L,R\)可能為\(0\))。顯然在確定了\(n\)\(L,R\)后,\(x\)也唯一確定了,因為在\(L,R\)已知的前提下,\(x\)的不同取值對應的\(n\)的可行范圍是無交的。由於\(x\)是確定的,所以我們可以把問題規約到\(x=1\)的情況上來。

對於\(x=1\),我們只需要安排一下左右兩棵子樹長成什么樣即可。首先\(n\)的取值下界是\(2^{L+1}+3\times 2^R-4\),之后每當在深度為\(d\)處選擇了右子樹進入,就會給\(n\)值加上\(\sum_{i=0}^d2^i=2^{d+1}-1\)的貢獻。這個問題等價於我們要安排兩個長度分別為\(L-1\)\(R-1\)\(01\)串,其第\(i\)位(\(0\)下標)的位值為\(2^{i+1}-1\),使得這兩個字符串的總權值加上\(n\)的取值下界后恰等於\(n\),求安排兩個\(01\)串的方案數。這個問題直接數位\(dp\)即可(或者像我一樣懶直接寫記搜)。

對於\(x\neq 1\),此時\(n\)的取值下界是\((2^{L+1}+2^{R+1}-3)x+2^R-1\),令\(k=(2^{L+1}+2^{R+1}-3),b=2^R-1\),此時\(x\)的取值一定為\(\lfloor\frac{n-b}{k}\rfloor\),於是便可以規約為\(n'=(n-b)\%k,x=1\)的問題。

總復雜度大概是\(O(\log^4n)\)\(O(\log^5n)\)

code

SDOI

Day1T1 快速查詢

維護全局標記\((a,b)\)表示維護的數\(x\)的實際值為\(ax+b\),這里需要始終保證\(a\neq 0\),初始時\(a=1,b=0\)
單點修改成\(val\)就把維護的值改成\(\frac{val-b}{a}\)。注意需要逆元需要實時維護。
加法直接加。
乘法若\(val\neq 0\)就直接乘,注意加法標記也要乘。否則操作就是全部賦值為\(0\)
賦值為\(val\)就把維護的數組全部清零,然后令\(a=1,b=val\)。顯然清零的復雜度不會超過單點修改的復雜度。
查詢直接查。
總時間復雜度\(O(q\log p+tq)\)

code

Day1T2 染色

首先有個很顯然的沒分裸暴力,記\(f_{i,j,k}\)表示\(dp\)到第\(i\)列,這一列的兩個格子的顏色分別是\(j,k\)的方案數,轉移顯然。

考慮子任務\(1,2\)。稱包含已染色格子的列為關鍵列,我們只需要考慮關鍵列之間的轉移即可。由於關鍵列有一種顏色已經確定,所以\(dp\)狀態中就只需要記另外一個格子的顏色即可,這樣的狀態數就只有\(O(nc)\)了。轉移時枚舉當前格子的顏色,可以做到\(O(1)\)轉移。

在這里需要求出這些東西的方案數(假設中間\(0\)的列數為\(z\)):

\(\begin{pmatrix}x&0&\cdots&0&x\\y&0&\cdots&0&y\end{pmatrix}\)
\(\begin{pmatrix}x&0&\cdots&0&y\\y&0&\cdots&0&x\end{pmatrix}\)
\(\begin{pmatrix}x&0&\cdots&0&x\\y&0&\cdots&0&w\end{pmatrix}\),它等價於\(\begin{pmatrix}x&0&\cdots&0&w\\y&0&\cdots&0&y\end{pmatrix}\)
\(\begin{pmatrix}x&0&\cdots&0&y\\y&0&\cdots&0&w\end{pmatrix}\),它等價於\(\begin{pmatrix}x&0&\cdots&0&w\\y&0&\cdots&0&x\end{pmatrix}\)
\(\begin{pmatrix}x&0&\cdots&0&w_1\\y&0&\cdots&0&w_2\end{pmatrix}\)

\(g_{z,0/1/2/3/4}\)分別表示上述五種情況下給中間的\(0\)染色的合法方案數。(代碼中\(g_z\)記的是\(z-1\)\(0\)的方案數)

轉移有點小復雜可以參考代碼。

求出\(g_z\)之后就可以愉快地\(dp\)了。每遇到一個關鍵列就大力討論轉移,復雜度\(O(nc)\)

對於子任務\(3,4\)中存在的兩個格子均已染色的列,稱其為分割列,可以發現分割列兩側的方案數獨立,因此需要實現分割列到關鍵列、關鍵列到分割列的轉移,分割列到分割列之間直接討論一下顏色是否相同乘上方案數就行了。

\(O(nc)\)地實現了上述內容即可獲得\(96\)分的好成績。發現我們對與維護的\(dp\)數組做的所有操作均為前一道題中的操作,因此Ctrl-C Ctrl-V再隨便改改即可通過此題。

96分code
100分code

Day1T3 世界地圖

對每個前綴\(i\)維護出前\(i\)列的\(\text{MST}\)將第一列和第\(i\)列的點設為關鍵點的虛樹,虛樹邊權為原樹的路徑最大值。合並的時候只需要對這個\(O(n)\)級別的虛樹做一次最小生成樹就行了。復雜度\(O(n(m+q)\log n)\)

code

Day2T1 熱鬧的聚會與尷尬的聚會

考慮如下構造方法:每次從圖中選取一個度數最小的點,將其以及與其相鄰的點刪去。設該操作一共進行了\(q\)次,第\(i\)次選取了點\(a_i\),刪除了包含點\(a_i\)在內的共\(b_i\)個點,假設\(b_t\)\(\{b_i\}\)的最大值,那么可以選取在第\(t\)次及以后刪除的點作為\(P\)集合(即熱鬧的舞會),選取\(\{a_i\}\)作為\(Q\)集合(即尷尬的舞會)。

不難發現\(Q\)一定是一個獨立集,且\(|Q|=q\)\(\sum_{i=1}^qb_i=n\)\(P\)集合此時的\(p\)值恰好為\(b_t-1\)。顯然\((p+1)b_t\ge n+1\),因此這種構造方法是可行的。

用智障的方法維護度數最小的點,復雜度\(O(Tm\log n)\)
code

Day2T2 移動金幣

階梯博弈。只有奇數層的石子有用,因此只需要考慮奇數層,偶數層用組合數分配即可。

后手必勝當且僅當奇數層石子數異或和為\(0\),也就是說每個二進制位的\(1\)的個數都是偶數。搞\(\log n\)個只有\(\frac{\frac{m+1}{2}}{2}+1\)項有值的多項式(暴力地)乘起來就好了,復雜度\(O(nm\log n)\)

code

Day2T3連續子序列

\(\text{Thue-Morse}\)序列有許多許多優美的性質(所以這題感到無從下手?)可以參考A010060

這里我們用到其中一條有趣的性質:\(\text{Thue-Morse}\)序列的另一種生成方式。

考慮先令\(T.M.=\{0\}\),隨后每次用\(01\)替換原序列中的\(0\),用\(10\)替換原序列中的\(1\),每次替換后序列長度翻倍,由此反復操作即可得到\(\text{Thue-Morse}\)序列,且每次操作后均可以得到一個其長度為\(2^k\)的前綴。

這種構造方法基於\(0\to01,1\to10\),可以將這個過程反過來,即\(1\gets 01,0\gets 10\),可以發現這個操作就是把字符兩兩划分成組后映射為\(0/1\)。注意對於任意一個給定的長度大於\(2\)的串\(s\),其均有兩種划分方案,當然如果某種划分方案中存在一組兩個字符相同,那么這種划分就是不合法的。

因此我們只需要考慮對串\(s+k\)(表示在串\(s\)后面加上\(k\)個字符)進行上述的操作即可。由於每次\(|s|\)\(k\)都會減小一半,因而使用記憶化搜索的總狀態數為對數級。注意要對一些遞歸邊界進行特判。
code


免責聲明!

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



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