2017年多校

2017 Multi-University Training Contest 1

多校第一场,所以电科没有准备div1的题目
Megumin:怎么全是数学题

1003 求所有点之前不同颜色出现的次数之和,那么可以单独考虑一种颜色,我们只需求出所有不包含这种颜色的pair即可,然后就dfs就好了

[Megumin的代码] (代码什么的,当然是不存在的呀)

1004 NTT

1005 数学(暂时不用补)5/37

1007 线段树+连通分量综合题(暂时不用补)4/11

1008 快速求第k大的数,首先,快排是不可取的,因为n是1e7,会T,但是快排的思想可以用在求这道题上,每当进行一次操作,则会分成两个区间,而我们只需要对k所在的区间进行操作即可,不过这样的复杂度稍大,只能卡过去。另一种做法是,我们首先将询问的位置bi从大到小排序,然后利用STL中的nth_element函数,几乎线性的求解第k大的数,而对于之后的操作,所需要进行计算的数组的大小不大于bi-1,这样减少了每次的计算量。

Megumin的代码

1009 仙人掌图+求前k大(暂时不用补)13/69

1010 生成函数(暂时不用补)10/36

1012 笛卡尔树 谁来教教我怎么读入 有了读入挂就可以AC了,思路很简单,当你枚举一个区间时,必然是有一个最小值的,那么这个最小值左边的区间和右边的区间的数是可以任意放的,因为无论选取什么数,他们的大小肯定互不相同(好一句废话),那么就有一个组合数了,之后不断枚举这个最小值的左区间和右区间即可。

[Megumin的代码] (代码什么的,当然是不存在的呀)

2017 Multi-University Training Contest 2

1002(12/105) hash+思维

1004(26/150) 数学

1005(22/218) 枚举+区间DP

1007 数论题,首先应该考虑用原根去求解\(f(i)\),之后再对式子化简,总之过程很考验数论推导的水平。

[Megumin的代码] (代码什么的,当然是不存在的呀)

1008 我们可以考虑每种颜色出现在多少个子矩阵内,由于一个矩阵可能会包含多个相同颜色的格子,那么关键的一步就是避免重复计算,我们对格子进行排序,并规定如果一个子矩阵包含多个相同颜色的格子,那他一定是计算在序小的格子上,这样的话,就可以避免重复,至于计算,很明显格子的下界是不存在的,我们可以枚举上界,当上界确定时,其左右界也可以确定,这样就可以计算了。有一步比较关键的优化是,如果这个格子头上有个相同颜色的格子,那么枚举到那一层就不需要计算了。

Megumin的代码

1010(5/57) 后缀自动机 树状数组 权值线段树 (基本不用补了)

2017 Multi-University Training Contest 3

1001 容斥,数位DP 0

1002 FWT 18

1003 枚举每一个数,计算其是第k大的的次数,相乘后求和即可。但是直接去计算的话,会重复经过很多无用点,即比当前数小的数,因此,用链表去维护所有大于等于当前数的位置,然后从小到大枚举每个数,每次枚举完,就把这个数删除。

[Megumin的代码] (代码什么的,当然是不存在的呀)

1004 字典树

  • 有点计数技巧的\(tire\)。首先我们可以一个一个地顺序插入数,在插入的过程中维护\(cnt[]\)表示该节点现在被覆盖次数,维护\(sum[i][j]\)表示第\(i\)位为\(j\)的数现在有多少个,维护\(sub[]\)表示该节点现在出现在第\(i\)个数之前前面某位不完全一样但第\(k\)位一样的数的数目总和(累加)。
  • 第i个数\(a[i]\)\(a[j]\)\(a[k]\)要满足题意,则\(a[i]\)\(a[k]\)前某位都一样,在第\(x\)\(a[i]\)\(a[j]\)的一样,\(a[k]\)\(a[j]\)的不一样。所以关键是找\(a[j]\)\(a[j]\)\(a[i]\)只需第\(x\)位相同,在计数的时候减去\(sub[]\)就行了。

1005 将2-n个节点分到k个集合中,使得每个集合与1的交集的斯坦纳树的权值之和最大。那么一棵树中的一个节点和其父亲节点应尽量分到不同的集合中,那么这样父亲节点到根节点的路径会被计算两遍,基于这个结论,我们在划分集合的时候,应尽量分离一个节点和其孩子节点。我们从每条边的贡献来考虑,每条边的贡献最多是以较低点为根节点的子树大小,加上k个集合的限制,那么每条边的贡献就是两者取min了,最后求和即可。

Megumin的代码

1006 对式子进行二项式展开,然后化简下,就可以用NTT去计算了

[Megumin的代码] (代码什么的,当然是不存在的呀)

1007 13

1009 基尔霍夫矩阵 21

1010 DP+cbq分治 34

2017 Multi-University Training Contest 4

1001 多项式+NTT 0

1002 KMP 44

1004 二分+线段树 题意是找一段连续的区间使得区间不同数/区间长度最小,可以表示成diff/len<=k化简得diff-k*len<=0,二分k,check的时候用线段树去维护区间最小就可以了

WQF的代码

1005 最短路 最终答案总可以表示成\(a*(2w)+b\)其中\(0<=b<2*w\),所以用d[i][j]表示走到i点,走的总距离模2*w的最小值距离,最短路预处理一遍就行了

WQF代码

1006 图论 1

1007 图论 集合V度数为1的一定要选,先将度数为1的先预处理掉,然后剩下的点都是度数为2的,是个欧拉回路,在回路上隔着取就行了

1008 LCA+并查集 先将轻重链划分出来,不仅仅是为了找LCA,也是为了在合并的时候以轻重链logn的特点,不断合并。

划分为若干条轻重链后,用最小生成树的思想来构造,在(a,b)这个区间内,区间内自己连接,也就是找到a,b的LCA,之后合并到LCA上,c,d也同样这么操作,最后把两个LCA合并起来就行

1010 二分+DP 19

1012 DP

  • \(dp[i][j][0/1]\)表示两个序列第\(i\)个和第\(j\)个作为结尾,并且是谷/峰。
  • 发现转移需要枚举\(i\)\(j\)再将符合条件的\(dp\)全加起来,复杂度太高。解决方法是另设\(pre[i][j][0/1]\)表示\(sum\{dp[k][j][0/1]|0<k<i\}\)。由于固定了\(i\),所以枚举\(j\)的时候将符合条件的\(pre\)加上。维护\(pre\)只需要在本次\(dp\)计算完后加上即可。

1013 分块 0

2017 Multi-University Training Contest 5

1001 卷积+bitset 肯定是预处理所有的k,本题可以等价于模2意义下的卷积,具体为什么看了半天也不是很懂

代码

1002 AC自动机+DP

  • 用了吉司机的思路。如果没有字符串横过中轴线,直接向两边\(dp\)就好。考虑横过中轴线的情况,可以枚举所有的可能的长度为最长长度的串,将出现的串记录在\(dp\)的初始值中,之后接着向两边\(dp\),就不用管横不横过的问题。
  • 其实还有其他更好的方法

1003 可持久化平衡树 (6/78)

1004 莫比乌斯反演+FFT 在有了FFT模任意素数的板子后,便不是问题了,将表达式写出后,利用莫比乌斯反演的经典式子替换gcd即可,最后用FFT求卷积

[Megumin的代码] (代码什么的,当然是不存在的呀)

1005 线段树+李超树 (3/17)

1007 DP (6/64)

1008 0/1背包

  • B数组其实是dp[1][j]表示A[1]~A[n]能组合成j的个数。转移方程为dp[i][j]=dp[i+1][j]+dp[i+1][j-A[i]]。移项得dp[i+1][j]=dp[i][j]-dp[i+1][j-A[i]]。
  • 求出字典序最小。因为dp[i][0]=1,故只要找到最小的j,使得dp[i][j]!=0,那么A[i]=j;

1010二分+轮廓线DP (3/67)

2017 Multi-University Training Contest 6

Megumin:下次勤奋点,先把水题切了

1001 (66/573) 线段树+扫描线 字典树上建线段树 hash离线

1003 优雅的暴力,从大到小枚举

[Megumin的代码] (代码什么的,当然是不存在的呀)

1004 (5/43) hash

1005 (3/10) 插头dp

1006 (1/15) 状压dp

1007 (34/108) 树状数组

1008 尺取法,通过枚举开始点和结束点去计算

[Megumin的代码] (代码什么的,当然是不存在的呀)

1009 (6/28) 动态点分治

1010 果然博弈题做得还是太少,竟一直想着用SG函数去解决这个问题,果然还是太年轻啊

[Megumin的代码] (代码什么的,当然是不存在的呀)

1011 求出韦恩图七块区域各自的人数,如果有一块人数小于0,说明数据有误

[Megumin的代码] (代码什么的,当然是不存在的呀)

1012 (40/170) dp+倍增

2017 Multi-University Training Contest 7

1001 (3/13) 中国剩余定理+二维NTT

1002 递归 所给的数不是满k叉树就是有一个叉不满,所以只要对不满叉的子树特殊处理就行,除此之外k=1,还得特判,不然树就退化成链,最后会TLE,找下前几项规律就行了

1003 (30/56) 数学+思维

1004 (8/53) 容斥+三元环计数(分块)

1006 状压+分组背包 小于\(sqrt(500)\)质数只有8个,这8个质数可以用分组背包的方式枚举保证不重复枚举,然后二维dp转移就可以了

1007 (18/47) 最小割

1009 比赛的时候没有做出来,有点伤心,事实上,除了p=3的特殊情况,其余满足条件的数均构成三元组,因此可以把模p不等于1的素数先排除掉,然后每个三元组三个数之间是成等比的(取模前),这个比值是方程\(x^3=1(mod p)\)除1外的解,用二次剩余即可计算得到,之后计算一遍即可。

[Megumin的代码] (代码什么的,当然是不存在的呀)

1010 (215/1573) 奇偶性+Lucas定理

1012 (3/7) DP

1013 (10/22) 抽屉原理+循环节

2017 Multi-University Training Contest 8

1001 线段树合并 考虑线段树合并,线段树维护三个信息,区间答案,区间和,还有区间有几个数,区间和和区间个数可以直接相加,这题会卡内存,写的时候要注意

1002 式子的化简倒是毫无难度,关键在于求解\(g[n]\),我只知道\(O(n\sqrt{n})\)的做法,很显然过不去,看了别人的题解发现是打表找规律,但是自己想了想事实上是可以证明的,我们从n-1推导n时,相当于每个数的分子+1,再多加一个1,而分子+1,结果只可能+1或者不变,那什么时候会+1呢,很显然分母是分子的约数的时候。那结果就是多加\(d[n]+1\)了,这样结合约数个数线性筛,就可以\(O(n)\)的去计算了,之后再求一遍前缀和即可。而对于\(f[n]\)的计算,由于\(\frac{n}{i}\)只有\(\sqrt{n}\)个取值,我们可以先预处理莫比乌斯函数的前缀和,然后\(O(\sqrt{n})\)的进行计算即可。

[Megumin的代码] (代码什么的,当然是不存在的呀)

1003 (2/14) cdq分治+归并排序

1004 (55/209) 堆

1005 (4/23) NTT

1006 AC自动机

  • 建立AC自动机。每次询问x、y时,将s[x]在AC自动机里跑一遍,把经过的点和fail点都标记了(也就是把所有可能的前缀都标记了)。再将s[y]跑一点,遇到标记的点更新长度。所以要记录每个节点的深度。

1007 (25/184) 阶梯博弈

1009 (26/334) 最小费用有向树

1010 (9/17) 最小割

2017 Multi-University Training Contest 9

1001 DP+hash

  • 如果顶点个数没那么大的话,令\(dp[u]\)\(u\)节点为根的树,向下延伸的最大价值。那么经过\(u\)的最长路要么分别经过两个孩子,要么经过某个祖先的孩子,所以只要枚举祖先更新值就好了。
  • 点很多,不能用常规数组去存,于是用map存\(dp\)值。因为修改的点最多\(m\)个,影响到的祖先最多有\(mlogm\)个,用map存足够了。如果查询的是没有修改过的点,其\(dp\)值直接用贪心去求,最多也只有\(logn\)级别的。

1002 先树链剖分,然后用线段树维护,判断x是否在[a,b]之间只要在线段树查询返回的时候,判断区间最值与a和b的关系

WQF代码

1003 (6/73) 极角排序+set

1004 (43/514) 模拟

1006 分成两个集合的最短路很好求,怎样才能使得所有的点对都出现呢,已知任意两个点在二进制表示上肯定至少有一位是不相同的,所以只要枚举二进制的位数,把k个点分成两个集合,需要分logn次即可。貌似这题将k个点随机化排序,分成两个集合也是可以过的。

1007 由于防御导弹的速度是大于攻击导弹的,那么,时间越长,防御导弹就越有可能能与攻击导弹相遇,因此考虑二分。当我们确定飞行时间时,我们可以求出每个攻击导弹的最远位置,而此时防御导弹可处的位置是以攻击导弹为圆心的一个圆内,如果此时防御导弹能够与所有的攻击导弹相遇,那么则这n个圆有交点,这样可以化成圆的面积并去做,然后我们只需要判断面积并是否大于0即可,那么可以考虑面积并边界上的点,这些点必然是某两个圆的交点,那么我们可以枚举两个圆的交点,判断其余点到这个交点的距离是否小于圆的半径即可,复杂度\(O(n^3log)\)

[Megumin的代码] (代码什么的,当然是不存在的呀)

1008 可以先取出最小的两个数\(a_0\)\(a_1\),那么\(a_0+a_1\)不属于原数列,继续找最小的数,重复操作即可。

Megumin的代码

1009 (31/310) DP+筛

1010 DP

  • \(dp[i][j]\)表示\(s2[1..j]\)能否匹配\(s1[1..i]\),且当前要匹配是\(s1[i]\)\(s2[j]\)。如果\(s2[j]='.'\)或者字母,直接\(dp[i][j] |= dp[i-1][j-1]\)
  • \(s2[j]='*'\)则有三种转移。\('*'\)不匹配字符、\('*'\)匹配前一个字符、\('*'\)“吃掉”前面一个字符。分别对应方程:\(dp[i][j] |= dp[i][j-1]\)\(dp[i][j] |= dp[i-1][j]\)\(dp[i][j] |= dp[i][j-2]\)。考虑特殊的字符串,比如空串和\(".*"\)

2017 Multi-University Training Contest 10

1001 (98/594) bidirectional BFS

  • 双向bfs的复杂度比正常bfs要开根号。状态可以hash一下。
  • 在搜索中注意step>10的状态不必再搜下去了。

1002 推出递推式后用矩阵快速幂计算

[Megumin的代码] (代码什么的,当然是不存在的呀)

1003 (4/36) 博弈+线段树

1004 (3/6) ???

1005 (10/52) 多项式+DP

1006 (2/18) DP+矩阵快速幂

1007 (2/357) 数学

1008 图论+快速读入 观察可得尽量使得两两匹配,保留的边最少,所以考虑二分匹配,树是特殊的二分图,但是本题数据太大了,匈牙利算法和优化的HC算法时限都不够,因为二分图最大匹配=最小点覆盖,本题就转化成求树的最小点覆盖,这是个经典的树形dp,求完之后分类讨论一下最大匹配数与k的关系就行了。另外这题卡普通读入,有点sb

1009 (3/42) ???

1010 我们可以利用差分去求解最少需要的机器数。对于总时间的求解,我们可以考虑求出每个机器开始和结束的时间,很显然当当前所需的机器超过已使用的机器时,必须使用新的机器,这样就能求得每个机器的开始时间。对于结束时间,我们考虑倒着求解,利用类似于求开始时间的形式,我们可以求得每个机器的结束时间。(本题机器开启后便不能停止,直到该机器结束,因此可以使用这样的解法)

Megumin的代码

1011 即求次短路,我们可以先SPFA求出每个点到1和n的最短路,然后枚举每条边,去更新结果即可

Megumin的代码

posted on 2017-08-01 19:19  ACGO  阅读(398)  评论(0编辑  收藏  举报

导航