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的时间差

posted @ 2020-01-06 22:53  ✡smy✡  阅读(225)  评论(4编辑  收藏  举报