WC2015-2019

代碼自己去uoj上看,懶得放鏈接了(


2015

k小割

強 行 三 合 一

前10分爆搜割集,然後check即可

後面40分,大概所有不是源點匯點的點都和源點有邊,和匯點有邊,那麼每個點連的兩條邊要選一條/兩條割.設其中較小權值爲\(a\),較大權值爲\(b\),那麼一個點有三種狀態\(\{a,b,a+b\}\),初始都爲第一種,那我們保存狀態集合,然後每次選最小的狀態輸出,然後拓展出次小的狀態,這個拓展要麼是當前指定點的\(a\)變成\(b\),或者\(b\)\(a+b\),要麼是後面找一個點的\(a\)變成\(b\)(滿足\(b-a\)比當前點\(b-a\)大),後面一種拓展可以改爲當前點由\(b\)\(a\),下一個是後面一坨點中\(b-a\)更大的且最小的點,他從\(a\)\(b\)

最後50分,考慮記錄一些割狀態,每次選最小的,然後拓展出次小割狀態,次小割一定要麼是強制選擇一個沒被割的邊,要麼強制不割某條割邊,換一條邊割,具體拓展方法是維護這個狀態的強制選與不選的邊集,然後先處理這些邊(強制選的強制斷開並加到答案裏去,強制不選的把容量改爲\(\infty\)),再跑個最小割,然後找出次小割,而次小割一定是某條不在割集中的邊割掉產生的,那這條邊就會代替割集中的一條邊,枚舉這條被代替的邊\((x,y)\),那麼新的邊一定在殘量網絡中\(S\)\(x\)的最小割上,或\(y\)\(T\)的最小割上.考慮這麼做的正確性,一個割集的次小割一定由割集與最小的邊有關,這條邊要麼在割集中,要麼不在,那麼用上面的方法就可以考慮到這兩種情況

混淆與破解

留坑待填

未來程序

task1

\(ab\mod c\)

task2

打表可得爲\({fib_{n-1}}^2\)

task3

要求\(n,\sum i,\sum i^2,\sum i^3,\sum i^4\),利用\((i+1)^k=\sum_{j=0}^k\binom{k}{j}i^j\)設計矩陣,矩乘後即可全部求出來

task4

如果方格里有\(a\)個位置爲\(1\),那麼count1答案爲\(a^2-a\)

count2是求對於每個爲\(1\)位置,離它最近的爲\(0\)位置的曼哈頓距離,直接把爲\(0\)位置丟進隊列開始bfs,對每個位置求最近曼哈頓距離即可

task5

求全\(1\)子矩陣個數,可以先固定上下界,然後如果某一列在這個上下界中全爲\(1\)就把對應位置標\(1\),然後就是求全\(1\)連續段問題.因爲一個極長的\(1\)(長度爲\(l\))的貢獻爲\(\frac{l(l+1)}{2}\),那麼可以考慮改爲先枚舉下界,上界依次往下移動,然後對於新增的全\(1\)列就減去前後兩個連續段貢獻,合併之後加上新的貢獻,可以利用並查集維護

task6

這題只能找循環節來做,但是暴力用map找不行,floyd也不大行,考慮brent算法,維護兩個指針以及一個\(lm\)值,每次移動第一個指針,如果找的過程中第一個指針和第二個相遇了就說明找到了環,如果第一個指針移動步數\(=lm\)就把第二個指針移到第一個指針處,同時\(lm=lm*2\)

task7

高級版數獨,搜的時候維護每一行,每一列,每一個方陣是否放了某個字符,如果這個字符沒在當前行/列/方陣出現過才能放;以及每次從能放字符數量最小的開始放

task8

偏序關係計數,大概偏序關係爲若干\(DAG\),寫出統計柿子然後推一推即可. 每個\(DAG\)都是獨立的,可以分開算.然後對於一個\(DAG\)我們考慮枚舉這個上面的數有多少種相同的,然後狀壓dp算出在有\(i\)種相同的數的情況下,上面的數分別爲其中某一種數的方案數,然後這個\(DAG\)貢獻爲\(\sum dp_{|S|,i}\binom{n}{i}\),最後乘法原理合並

task9

前四個不解釋,枚舉/搜索即可

1984
123456
chenlijie
$_$

後六個中,前四個都是單個單詞,第五個爲單詞+空格+單詞,第六個爲單詞+單詞.不知道你們有沒有注意到第二個cpp(或第十個cpp)中有個詞典,直接在裏面選單詞搜即可

名言爲we hold these truths to be self-evident

task10

可以通過dp技巧算出每個字母對應是加幾次___,然後每個單詞可以看成是每一位上的字母要用若干次,可以根據他的含義設計出\(dp_{i,j}\)表示長度爲\(i\)的串,第\(j\)位算的次數,轉移按照他的意思轉移即可(每個真子串都要算一次)

2016

挑戰NPC

考慮對一個籃子放的球數所產生的貢獻入手.如果是0或1個球就產生1的貢獻,如果時候2或3個求就產生0的貢獻.不妨把這個貢獻考慮到匹配上去,即如果一個籃子只有0或1個球匹配,就利用額外的一個匹配產生貢獻.具體做法是可以將一個籃子拆成三個點,然後連成三元環,再把原來的每條邊拆成三條邊連到對應點上,跑個帶花樹,求出來的最大匹配-球數就是答案.構造方案直接輸出對應球的匹配點即可.注意帶花樹時要從球點開始做,否則球點可能沒有匹配點(雖然答案是不變的)

論戰捆竹竿

here

鏖戰表達式

一開始看成鏖戰多項式

區間翻轉+可持久化,顯然是可持久化Treap.具體實現時,因爲合併要講究優先級,那麼每個合併Treap的時候先比較符號優先級(元素一定是葉子節點),再用隨機權值比較即可.剩下的東西基本上都可以在普通平衡樹以及文藝平衡樹中找到,實在不會去百度啊,實在是懶得講了QAQ.可能實現時要注意卡操作常數,例如一開始建樹要建的儘量平均

2017

\(\large\mathcal{WDNMD}\)

待填...

2018

通道

不妨先考慮兩棵樹怎麼做,我們要求的是\(dis1(x,y)+dis2(x,y)\),這等價於\(de1_x+de1_y-2de1_{lca1(x,y)}+de2_x+dis2(x,y)\),那麼我們dfs第一棵樹,並考慮\(lca1(x,y)\)的貢獻.我們在第二棵樹上的每個點下面都加一個點\(x'\),連邊邊權爲\(de1_x\),那麼點對\((x,y)\)剩下的貢獻就是第二棵樹上\((x',y')\)的距離.在第一棵樹上我們就在lca處合併兩棵子樹,然後計算\(x,y\)分別在兩棵子樹內的貢獻,就是路徑兩端點分別爲兩棵子樹對應在第二棵樹上的點的最長路徑,也就是直徑,我們維護第一棵樹子樹內所有點在第二棵樹上的虛樹的直徑(只要維護兩端點),合併的時候只要讓兩個子樹的對應的四個點兩兩組合取最長路徑就是直徑

然後是三棵樹.我們對第一棵樹使用邊分治,因爲這樣可以把樹分成兩部分,方便計算貢獻.然後這條重心邊分開的兩個子樹,把這裏面的點分別稱爲A點以及B點,並在第二棵樹上建虛樹,然後在虛樹上dfs,每次在某個lca處統計不同子樹內A點到B點的貢獻.因爲在第一棵樹上用了邊分治,以及第二棵樹上枚舉lca,那麼\(dis1(x,y)-2de2_{lca2(x,y)}\)現在是確定的,還剩下\(de2_x+de2_y-dis3(x,y)\),這裏就參照兩棵樹的做法,維護子樹內AB點集的直徑,然後類似的做就完事了

州區劃分

先考慮暴力做法,設\(f_s\)表示選出的點集爲\(s\)的答案,這是因爲你新加進來一個省,它的貢獻只和自己以及前面加過的點有關,轉移直接枚舉下一次加進來的子集.這裏一個子集能加進來說明不存在歐拉回路,也就是隻要這個點集導出子圖不連通或者存在度數爲奇數的點即可.複雜度\(O(n^22^n+3^n)\)

然後可以發現剛剛的\(O(3^n)\)的算法是在做一個叫子集卷積的東西,這個子集卷積有點像位運算卷積,不妨先往\(FWT\_or\)上考慮.我們想要的是\(f_s=\sum_{t\subset s} f_tg_{s\setminus t}\),可是\(FWT\_or\)計算的是\(f_s=\sum_{t|d=s}f_tg_d\),這會導致兩個有交的子集的貢獻被算進來.那就考慮什麼樣的兩個子集並起來沒有交,可以發現如果我們加一維表示集合內1的個數,那麼一個卷積合法就要使得\(popcount(t)+popcount(d)=popcount(s)\),所以當狀態爲\(f_{s,i}\)時,狀態合法當且僅當\(popcount(s)=i\),這個在轉移的時候注意一下就好了,複雜度\(O(n^22^n)\)

即時戰略

其實可以先考慮鏈的部分分,我們維護當前已經確定的鏈的兩個端點(初始時爲1),然後對於沒確定的點\(x\)每次選擇一邊進行\(explore\),如果能得到一個新的點就繼續操作直到把\(x\)拓展出來;否則就對另一邊進行這個操作.可以證明複雜度爲\(o(nln(n))\)

然後是樹的做法,暴力是對於當前點\(x\),從根開始\(explore\),如果是已經知道的點就在這個點\(explore\),直到找到\(x\).如果我們是從另外一個點開始的,那麼考慮這個點到根的鏈,我們可以在這個鏈上二分,如果拓展到一個不在鏈上的點就可以跳出這條鏈,並且遞歸此操作.由這個,以及題目裏的點是依次加進來的,就考慮lct維護一些鏈,因爲lct中每個splay都是樹上直上直下的一條鏈,那麼從根對應的splay的根開始,每次在這個點上\(explore\),就相當於在這條鏈上二分,如果詢問得到的下一個點在這個點往上方向就跳到這個點在splay上的左兒子,如果在往下方向就跳到這個點在splay上的右兒子,否則直接跳到下一個點的splay上.根據那套理論,複雜度是\(O(nlogn)\)

2019

數樹

Orz Iaofu

task0

可以發現,題目的意思是兩棵樹\(T_1T_2\)的貢獻爲\(y^{n-|E(T1)\cap E(T2)|}\),所以只要知道這兩棵樹有多少邊一樣就行了

可以發現\(y=1\)時每種情況都是1的貢獻,所以輸出有多少種樹的情況即可

task1

下面的\(y\)都是原來的\(y^{-1}\),算的東西都是所有可能邊的交集的貢獻,所以答案最後要乘上原來的\(y^n\)

直接枚舉兩棵樹的交集算貢獻不太行因爲不能直接確定是否這個邊集就是最終的交集,我們需要一些神必轉化.考慮一個邊集在整個的兩棵樹邊集交中的貢獻,欽定一個大小爲\(i\)的集合貢獻爲\(v_i\),有\[y^{|S|}=\sum_{i=0}^{|S|} \binom{|S|}{i}v_i\]有點二項式的味道,然後把左邊變成\((y-1+1)^{|S|}\),則有\(y^{|S|}=\sum_{i=0}^{|S|}\binom{|S|}{i}(y-1)^i\),然後\(v_i=(y-1)^i\)

所以現在枚舉一個邊集,如果它是兩棵樹邊集交的子集,那麼就有\((y-1)^{|S|}\)的貢獻,否則貢獻爲0,所以只要在乘上它爲多少種兩棵樹的邊集交的子集就好了.我們就強制這個邊集在兩棵樹裏都出現,也就是枚舉第一棵樹的邊集子集,然後算出包含這個邊集的另一棵樹個數即可.如果這些邊形成了\(m\)個連通塊,根據\(prufer\)序列,我們把這些連通塊看成一個點,然後就只要知道每個連通塊大小(即一個大小爲\(a\)的連通塊連出去一條邊的方案爲\(a\),也就是在\(a\)個點裏任選點連邊),以及在\(prufer\)序列中出現次數(即度數-1),就能算出包含這些連通塊的樹個數.大概爲\[(m-2)!\sum_{\sum d_i=m-2}\prod_{i=1}^{m}\frac{{a_i}^{d_i+1}}{d_i!}\]\[\prod_{i=1}^{m}a_i(m-2)!\sum_{\sum d_i=m-2}\prod_{i=1}^{m}\frac{{a_i}^{d_i}}{d_i!}\]

現在關心\(\sum\)後面那坨,可以先把\(prufer\)序列第一個位置提到前面來算貢獻,再枚舉這個位置是被哪個連通塊用了,可得\[(\sum_{j=1}^{m} a_j)(m-1)!\sum_{\sum d_i=m-1}\prod_{i=1}^{m}\frac{{a_i}^{d_i}}{d_i!}\]
\[n(m-1)!\sum_{\sum d_i=m-1}\prod_{i=1}^{m}\frac{{a_i}^{d_i}}{d_i!}\]

接着把第二個,第三個位置...也提出來,依次遞歸下去,可以知道後面的東西其實就是\[n^{m-2}\prod_{i=1}^{m}a_i\]

然後考慮樹型dp算所有連通塊劃分的貢獻,即\((y-1)^{n-m}n^{m-2}\prod_{i=1}^{m}a_i\),只要把\((y-1)^nn^{-2}\)提到前面,那每個連通塊貢獻就是\((y-1)^{-1}na_i\)去設\(f_{i,j}\)表示\(i\)子樹內,\(i\)所在連通塊大小爲\(j\)的貢獻,複雜度\(O(n^2)\)

優化的話考慮\(\prod a_i\)的組合意義,即先把連通塊選好,然後每個裏面選一個關鍵點的方案,把狀態改爲\(f_{i,0/1}\)表示\(i\)所在連通塊是否選了關鍵點即可,轉移類似於一個揹包,複雜度\(O(n)\)

task2

繼續考慮上面的那一坨東西,因爲兩棵樹都不確定,那就枚舉一個邊集,這會分成若干連通塊,再算這些連通塊在多少種兩棵樹的情況裏.這裏改變枚舉順序,先枚舉連通塊,然後考慮所有連通塊內部的連邊情況以及被多少種兩棵樹包含,顯然根據\(prufer\)序列,大小爲\(a\)的連通塊內部連邊方案爲\(a^{a-2}\).我們枚舉一個連通塊劃分,假設有\(m\)個連通塊,第\(i\)個大小爲\(a_i\),就可以先把柿子寫出來\[ (y-1)^{n-m}(\prod_{i=1}^{m}{a_i}^{a_i-2})(n^{m-2}\prod_{i=1}^{m}a_i)^2\]

\(n^{-4}\)\((y-1)^n\)提出來,令\(f_i=(y-1)^{-1}n^{2}i^i\),即一個連通塊的貢獻,那放在這裏其實就是求所有連通塊森林的貢獻,先把這個東西的EGF寫出來\(F(x)=\sum_i\frac{f_i}{i!}x^i\),則連通塊森林貢獻的生成函數就相當於是\(e^{F(x)}\),最後把算出來的多項式的第\(n\)項乘\(n!\)作爲答案即可,複雜度\(O(nlogn)\)

遠古計算機

首先你要看懂題目

這裏是一些tips: 每個計算雞都有一個指針,初始爲開頭,每一輪操作指針所在一行,如果不是`jmp`就移到下一行,沒有下一行就回到開頭
除了`jmp`之外,剩下的`jz` `jnz` `jgz` `jsz`似乎有鍋(霧),~~其實就是我用了,然後發現不對~~ (如果沒鍋可以告訴我一聲qwq)
注意`val`處是可以填`a`/`b`的
另外真正有用的操作只有`mov` `jmp` `read` `write`,剩下的操作頂多是用來佔位置的(霧)

task1

先看懂題目,然後

node 1
read 0 a
write a 0

task2

只有兩個存儲單元,而如果硬要做是要三個單元的,所以考慮打表,把表打成

write 0 0
write 1 0
write 1 0
write 2 0
...

這樣的形式,然後前面根據讀入的數跳轉到對應行即可

task3

搜出1到n最短路,然後只考慮最短路上的點,奇數位置先讀入在輸出,偶數位置相反

task4

大概瞎貪心+隨機一下,rand一個排列,然後依次考慮,對每個點找到最短的操作路徑,滿足在路徑上對應操作時不會和其他前面的操作衝突,並標記操作過的時刻即可

task5

他給的是一個網格圖,並且1~10在最下面依次排列,91-100在最上面依次排列,然後按照下述方法構造即可

注意左半邊的每條路線要比它左邊那條路線晚2個時間出發,右半邊類似,還有中間兩條路徑出發時間要有1的時間差

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章