省选前的做题记录(Round2)
Posted guessycb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了省选前的做题记录(Round2)相关的知识,希望对你有一定的参考价值。
[CF1109B] Sasha and One More Name
先把无解情况aaabaaa、aaaaaa判掉,然后我们可以证明答案不会超过2。
对于一个回文串,两个指针从两端向内移动直到字符发生变化,在这里看一刀然后交换左右两端即为一种合法方案。
所以我们只需要判断答案是否能为(1),暴力判即可。
[CF1109C] Sasha and a Patient Friend
假设我们有一个序列数据结构,那么先考虑每个结点需要维护哪些值才能支持合并左右儿子。
维护:
当前点时刻(time),区间左右端点时刻(Ltime,Rtime),当前点速度(v),区间右端点速度(rv)。
区间通过变化量(res)、区间变化量最小前缀和(mn)。
合并大讨论一下即可。
对于查询答案,我们可以在数据结构上二分。
这个数据结构需要支持:单点插入、单点删除、区间(split),直接用(treap)之类的平衡树支持一下。
[CF1109D] Sasha and Interesting Fact from Graph Theory
枚举一下路径((a,b))上有多少条边。
然后Cayley定理随便算算:(Ans = sum_{j=1}^{n-1} inom{m-1}{j-1}inom{n-2}{j-1} (j-1)! m^{n-1-j}(j+1)n^{n-j-3})
[CF1109E] Sasha and a Very Easy Test
注意到是在模(mod)意义下,所以我们将质数分为(mod)的因子、非(mod)的因子。
显然本质不同的(mod)因子不会超过(10)个。
直接维护区间乘法,对于(lazy)标记,我们额外维护非(mod)因子的积、每种(mod)因子的个数。
那么区间除法时,沿着线段树一路将(lazy)推到叶子结点后,我们就可以知道该点(mod)因子的构成。
在叶子结点重新计算当前点的值即可。
[CF1109F] Sasha and Algorithm of Silence‘s Sounds
首先考虑维护无环性。
设(p_r)表示最小的左端点满足([p_r,r])的点不会构成环。
显然有(p_r leq p_{r+1}),也就是说(p_r)的移动单调,随着(r)的增大而增大。
所以我们只需要支持:动态加边、删边、判断连通性,用(LCT)维护即可。
然后考虑维护连通性。
当加入边([pos,r])时,((pos,r))这个区间的联通块个数不变,而([p_r,pos])这个区间的联通块个数会减一。
所以用线段树维护每个左端点的联通块个数,维护区间最小值和区间最小值个数来统计答案。
[JXOI2018]游戏
显然只有无非1约数的数会对最终时间产生影响,所以先把倍数全部去掉。
然后不就暴力枚举结束时间,组合数算一算就行了。
[UOJ308] UOJ拯救计划
看到(\\%6)我们可以想到拆成算(\\%2,\\%3)的答案,最后再手动(CRT)得解。
根据预分配计数法,标号方案 = 最小表示法方案 * 标号分配方案。
而选(c)种标号的标号分配方案 = (A_K^c),故若(\\%t
eq 0),则(c leq t-1)。
所以我们实际只需要算使用1、2种标号的方案数。
使用1种标号的可以直接判,使用2种标号那么原图必须是二分图也直接判,注意细节。
[UOJ310] 黎明前的巧克力
我们可以把问题转化为:选出所有异或和为(0)的集合,若该集合大小为(s),则对答案贡献为(2^s)。
设(f_{i,j})表示前(i)个元素,异或和为(j)的方案数。
那么转移:(f_{i,j} * 2 o f_{i+1,j xor a_{i+1}})、(f_{i,j} o f_{i + 1,j})。
这本质上其实就是(n)次(fwt),观察每次(fwt)的数组(A_i),(A_i)只有(0,a_i)两个位置上有值。
我们可以把(A_i)全部预先(fwt)好,那么转移就变成了每一位对位相乘。
根据异或(fwt)原理,我们有:(fwt_i' = sum_{j=0}^{2^n - 1} (-1)^{bitcount(i and j)}fwt_j)。
也就是说(A_i)进行(fwt)后,每个位置只会是(3)或(-1)中的一个。
我们目标求每一位的积,但由于我们知道每一位变量只有两种取值,所以可以先求每一位和,然后解方程得解。
而和的(fwt)等于(fwt)的和,所以就只需要做一遍(fwt)了。
[CF1117G] Recursive Queries
考虑每个点被算到的贡献,可以发现就是它左右两侧的递增单调栈的长度。
两边的单调栈会互相干扰很烦,所以我们可以一边一边算。
以算右边为例,从左往右扫维护前缀单调栈,每次就是让一段的右侧单调栈长度加一,查询即求区间和。
[UOJ386] 鸽子固定器
先把元素按照(s)排序,按照(d)从小往大处理,考虑当前(d)最小的位置(p)什么时候会被算到。
我们先考虑区间右端点的位置。
若区间右端点在([1,p))或([p+m,n]),显然不会取(r),因为取(r)会导致(sum v)减小,方差变大。
所以右端点一定在([p,p+m)),在考虑左端点会在哪里。
设选定的右端点为(r),若左端点位于([1,r-m]),那么(p)一定不会被选到。
因为此时方差固定,目标为最大化(sum v),而(v_p)最小,选取显然不优。所以左端点一定为(r-m+1)。
综上所述,若(p)被选中,则选取区间一定是(rin [p,p+m))长度为(m)的连续区间。
处理完(p)位置的答案后,这个元素在之后的方案中都不会用到,直接删掉然后递归处理即可。
上述所有操作都可以用链表直接维护。
[UOJ387] To Do Tree
有限选子树内深度最深的点,不选肯定不优,所以就做完可。
[CF1117E] Decypher the String
注意到(26^3 > n),所以分三层对每个位置标识((id_1,id_2,id_3)),然后三次分别针对(id_{1,2,3})询问。
[UOJ389]白鸽
先考虑如何构造一个合法的带权欧拉回路。
我们先随便定向((u o v)),那么此时有一些点的度数不合法。
而网络流有着流入量 = 流出量的优良性质,所以可以类似最大权闭合子图构建网络流模型。
我们有两类点集(S_1,S_2),其中(Init_{s_1} > 0)、(Init_{s_2} leq 0)。
分类讨论一下原图的边((u o v)):
若(uin S_1)、(vin S_2),那么反向后(Init_u)、(Init_v)绝对值增加,这显然是在帮倒忙,故这条边一定不会取反。
若(uin S_i)、(vin S_i),取反后是相当于是内部(Init)转移,恰好对应流量转移。
若(uin S_2)、(vin S_1),取反后使得(Init_u)、(Init)绝对值减小,可行。
故对于端点不同侧的边,我们只会取反((uin S_2,vin S_1))。
所以连边为:(S o {S_2})、({S_1} o T) 。
然后考虑流量上界应该要设多少。
取反一条边后,(u)、(v)点的(Init)变化量为(2)而不是(1),这个就非常的讨厌了。
处理方式是这样的:把流量上界设为(frac{|Init_u|}{2}),因为合法方案中(|Init_u|)一定为偶数。
最后来讨论一下费用,我们从原点引一条射线,当路径穿过射线就表示绕了一圈(带符号)。
所以我们给所有穿过射线的边初始定为顺时针,然后让取反的代价为(2)即可。
注意此题普通(EK)过不去,需要使用多路增广最小费用流。
[UOJ391]鸽举选仕
挺有意思的一道题,题解戳这里。
[HAOI2018]反色游戏
看到这货第一想法肯定是按点建线性基,答案就是(2^{自由元})。然后发现这并没有什么鸟用......
但是这启发我们答案肯定类似(2^c)。
我们先来考虑一下,给定一棵树,如何构造答案一种合法方案。
显然如果黑点个数为奇数那么就无解了,否则一定有解。
一种与后续算法相关的构造是:把黑点两两匹配,然后依次对每对黑点之间的路径取反。
如果是一棵树,答案显然就是(1)。
考虑加入一条非树边,若该边不取反则无影响,若该边取反,则把原方案中两点路径取反后又是一种合法方案。
所以对于一个联通块,(ans = 2^{|E| - (|V| - 1)})。
设全局联通块个数为(cnt),则全局答案为(Ans = 2^{|E| - |V| + cnt} = 2^{|E|-|V|}* 2^{cnt})。
所以我们只需要维护删去某点后联通块的个数以及全局是否合法,用点双里的一些技巧即可实现。
[HAOI2018]奇怪的背包
若选择元素(a),则该元素能够构造出的数为(k gcd(a,P))。
对于元素(c_1,c_2),它们能够构造出的数为(k gcd(c_1,c_2))。
把(P)的约数处理出来,设(f_{i,g})表示前(i)个约数、(gcd = g)的方案数,转移随便弄弄。
当查询(t)时,(Ans = sum_{d|t} f_{|np|,d})。
注意到(d|t,d|P),所以(d|gcd(t,P)),故可以把答案全部预处理出来,这样回答就只要(O(logn))了。
[HAOI2018]字串覆盖
一个显然正确的贪心:从左往右,能选就选。
我做这个题的时候是这样发现正解的:看部分分(|r-l|>2000),(|r-l|<50)。
然后(n = 10^5),所以(frac{n}{2000} = 50),嗯(抓耳挠腮)什么鬼???
所以自然就是数据分治啦。当(n>2000)时,直接暴力向后跳,最多跳(frac{n}{r-l} = 50)次。
当(n < 50)时,可以发现串(A)最多提供(50n)个本质不同的串,所以完全可以暴力把每个位置都弄出来。
弄出位置后,询问就是一个比较经典的模型了,倍增即可。
至于(nin [50,2000])的直接当作(n>2000)做就行了,反正这种询问的次数不会特别多。
上述操作全部用(SAM)+线段树合并兹瓷一下。
[JSOI2018]潜入行动
可以列出一个白痴(dp):(f_{u,j,0/1,0/1})表示(u)子树内放了(j)个监听器,当前点是否合法,是否放了监听器。
转移一波大讨论。
对于第二维(j),用一下(CF)最近新出的科技卡一下(size)复杂度就变为(O(nK))了。
[JSOI2018]防御网络
树边的贡献是(2^{sz}*2^{n-sz})直接算掉,考虑算环的贡献。
首先我们得到环上每个点挂的子树大小(size),这个可以用点双的技巧(O(1))得到。
加设我们选择了环上的若干点,那么最优决策是:选出环上的最大间隙,然后删掉。
破环成链,设(f_{l,r,k})表示区间([l,r])中,不考虑首尾相连的间隙,最大间隙为(k)的方案数。
转移固定左端点,枚举右端点:(f_{l,r,k} = sum_{p = 0}^{r-k-l} f_{l,r-k,p} + sum_{p=r-k+1}^{r-1} f_{l,p,k})。
这是一个二维矩阵形式,用二维前缀和优化到(O(n^3))即可。
[JSOI2018]绝地反击
暴力的想法是:二分答案求圆弧交,那么假设能够确定了任意一个终点,做二分图匹配即可。
显然一定会有一个终点卡在圆弧边界上,枚举卡在哪里,这样就可以做到(O(n^4logn))了。
但不难发现第一个终点本质不同的旋转角度可以集中在([0,frac{2pi}{n}])这个弧度区间中。
那么把每个圆弧交的边界算出来,每转动一下,二分图最多只有一条边删除、一条边加入。
这不就直接上退流了呗......
删边时将((u,v))分别退去(1)的流量,加边就直接加,这样复杂度秒变(O(n^3logn))。
[JSOI2018]战争
考虑((x_A + d_x , y_A + d_y) in B),即(A + delta in B),那么(delta in B - A)。
所以求(B)、(-A)的闵可夫斯基和,那么问题转化为判断(delta)是否在凸包内,这个可以直接二分实现。
[JSOI2018]机器人
看到这道题先写了一个暴力,然后打表就发现了一堆乱七八糟的性质。
有用的性质:设(d = gcd(n,m)),则合法路径的行走方案每(d)步一个循环,这个目前不会证。
我们设(d)步中向下走(dx)步,向右走(dy)步,则(dx = dy)。
考虑(dx)、(dy)满足什么条件时,该方案合法。
结论:若(d = gcd(n,m))、(dx + dy = d)、(d_x perp n)、(d_y perp m),则方案合法。
我们来证明一下。
对于格子((x_i,y_i)),我们设从((1,1))经过(kd + rest)步到达((x_i,y_i))。
我们把格子按照(rest)分组,那么每一组一定恰好有(frac{nm}{d})个格子。
由于前(d)步的移动一定不交,所以我们实际上只要证明:对于任意一组,恰有(frac{nm}{d})个格子与待证限制条件互为充要条件。
Case1:证明充分性
若(d_xperp n)、(d_y perp m),则(x)的周期(= frac{n}{gcd(n,d_x)} = n),(y)的周期(= frac{m}{gcd(m,d_y)} = m)。
所以((x,y))的周期 (= frac{nm}{gcd(m,m)} = frac{nm}{d}),合法。
Case2:证明必要性
反证。设(gcd(d_x,n)=s_1)、(gcd(d_y,m) = s_2),其中(s_1,s_2)至少一个(>1)。
根据扩欧,我们设:(t = gcd(d_x,d) = gcd(d_x,d_y) = gcd(d,d_y))。
类似的我们可以得到(x)的周期(= frac{n}{s_1}),(y)的周期(= frac{m}{s_2}),则((x,y))的周期(= frac{nm}{s_1s_2gcd(frac{n}{s_1},frac{m}{s_2})})。
我们只需要证明,若不满足待证限制条件,则(frac{nm}{s_1s_2gcd(frac{n}{s_1},frac{m}{s_2})} < frac{nm}{d}),即有点没有被经过。
上述式子化简可得:需证若不满足待证限制条件,则(s_1s_2gcd(frac{n}{s_1},frac{m}{s_2}) >d)。
case2.1:若(t = 1),则:
由于(d_x perp d)且(s_1|d_x),所以(s_1 perp d)。同理可得(s_2 perp d)。
所以(gcd(d,s_1s_2) = 1),即(gcd(frac{n}{s_1},frac{m}{s_2}) = d),又(s_1s_2 > 1),得证。
case2.2:若(t > 1),则:
因为(t|d),所以(t|n,t|m)。
又因为(t|d_x,t|d_y),所以(t|s_1,t|s_2)。
故(s_1s_2 gcd(frac{n}{s_1},frac{m}{s_2}) = coef*td > d),得证。
Case3(补充):由于(d_xperp n,d_yperp m),所以对于同一(rest),每个点坐标有唯一表示,故路径不会相交。
接着就可以DP啦,首先枚举一对合法的(d_x,d_y)。
那么对于一种方案,路径长度 = 路径上到每一个障碍的时间的最小值。
我们现在已知(d_x,d_y),需要(dp)的是(d_x,d_y)的具体走法。
把矩阵压缩到(d_x * d_y)大小,对于矩阵内每一个点,处理后继每一个障碍到达时间的最小值(mn)。
然后从矩阵左上方往右下方走做一遍网格图(dp)即可,复杂度(O(Tn^5))松一松就过了。
[UOJ326]几何冲刺
首先把红点、蓝点以原点为中心极角排序。
固定起点(P),对于蓝点(B)和三角形(AOP),(B)在(AOP)中的条件为:角(AOB)(ge)角(BOP)、角(APO)(ge)角(BPO)。
以极角序逆时针移动以满足第一个条件,第二个条件直接开一个变量纪录最小值即可。
[UOJ327]去月球
对于单次询问,我们显然可以通过单调栈在(O(n))的复杂度算出答案。
后面的解法非常的仙,构造一棵神奇的操作树:
从左往右做单调栈,若入栈这从当前点前往对应儿子,若弹栈则回到父亲结点。
然后会发现,任何完美括号序列在树上一定对应一条从(u)出发回到(u)的路径,那么路径长度就是不能匹配上的元素个数。
[UOJ328]量子破碎
操作二使得我们能够进行(fwt),考虑异或(fwt)原理(fwt_i' = sum_{j=0}^{2^n-1} (-1)^{bit(i and j)}fwt_j)。
对量子数组做(fwt)然后询问得到位置(t),
那么我们可以知道(fwt_t = frac{1}{sqrt{2}}((-1)^{bit(x and t)} + (-1)^{bit(y and t)})
eq 0)。
所以((-1)^{bit(x and t)} = (-1)^{bit(y and t)})。
所以((-1)^{bit((x xor y)) and t} = (-1)^{bit(x and t) + bit(y and t)} = 1)。
然后就能排除掉(bit((x xor y) and t))为奇数的((x xor y))了,一直做下去直到只剩下一个合法解。
[WC2019]I君的商店
首先明确,我们每次返还的信息形如:(a_xleq a_y)、(a_x ge a_y)。
对于(task_3),设最大值在左端,则用(a_x + a_{x+1} ge 1)二分大概分界点,然后用(K)的奇偶性得解。
先考虑一个(7n)的做法:
我们先用(2n)的时间找到序列的一个最大值(mx)。
每次取出两个未确定的数(a_x,a_y),比较((a_x+a_y,mx))、((a_x,a_y))。
若(a_x + a_y le mx),则(a_x,a_y)中较小的一个为(0)。反之,(a_x,a_y)中较大的一个为(1)。
然后来看(5n)的做法。
我们考虑去掉找最大值(mx)的过程。
取出两个元素(a_x,a_y),设当前最大值为(a_{mx}),则比较((a_x,a_y))、((a_x+a_y,a_{mx}))。
不妨设(a_x leq a_y)。
若(a_x+a_y leq a_{mx}),则可以推出(a_x = 0)。 否则有(a_y ge a_{mx})。
若(a_y ge a_{mx}),则把(a_mx)扔到栈中去,让后令(mx = y)继续处理。
这样到了最后,我们确定了若干元素(=0),有一个单调递增的栈满足(y_1leq y_2 le y_3...le y_{|stack|}),有一个未确定元素(z)。
可以肯定的是(max(z,y_{|stack|}) = 1)。
那么我们先用(task_3)的方法二分出栈中的大概分界点,然后根据(K)的奇偶性进行讨论。
设二分出的未确定位置为(p)。
若当前(1)的个数与(K)奇偶不同,则(a_z,a_{y_p})中有一个(1),询问((a_z,a_{y_{p}}))。
若当前(1)的个数与(K)奇偶相同,则(a_z = a_{y_p}),询问((a_z + a_{y_p},a_{y_{stack}}))。
询问次数变为了(O(5n + logn + c))。
[WC2019]数树
首先明确一下,对于任意一种方案,设(m)为两棵树的重合边数,则(ans=y^{n-m})。
所以我们实际只需要算(y^{-m}),下文中默认(y = y^{-1})。
(task_1):来搞笑的,不用管就是了。
(task_2):
不难想到(cayley)定理,即枚举两树重合的联通块,然后把这些联通块组合在一起。
然而这样会面临组合时非法组合的问题。
我们用一个巧妙的办法解决它:(y^k = sum_{j=0}^{k} inom{k}{j} (y-1)^j)。
这个式子的组合意义:对于边集(E),对于每种包含它的方案,会产生((y-1)^{|E|})的贡献。
所以我们令(y = y - 1),然后就不用考虑非法组合的问题了。
可以写出一个(dp):设(f_{u,j})表示以(u)为根的子树内,与(u)相连的联通块大小为(j)的系数和。
转移根据(cayley)定理:(way = n^{m-2} prod_{i=1}^m sz_i),统计(prod_{sz_i})与边权(y)的系数和即可。
可以注意到(prod_{i=1}^m sz_i)的组合意义:在每一个联通块内各选一个关键点的方案数。
所以直接设(f_{u,0/1})表示(u)所在的联通块是否选择了关键点的方案数,这样(dp)复杂度就变成了(O(n))。
(task_3):
设(f_i)表示有(i)个重合联通块的方案数。
和上面一样先拆组合意义避免容斥:令(y = y - 1)。
显然有:(f_i = sum_{sum_{j=1}^i a_j = n} frac{n!prod_{j=1}^i frac{a_j^{a_j - 2}}{a_j!}}{i!} (n^{i-2} prod_{j=1}^i a_j)^2)。
答案(Ans = sum_{i=1}^n y^{n-i} f_i)。
带入有:
(Ans = sum_{i=1}^n y^{n-i} sum_{sum_{j=1}^i a_j = n} frac{n! prod_{j=1}^i frac{a_j^{a_j - 2}}{a_j!}}{i!} (n^{i-2} prod_{j=1}^i a_j)^2)。
所以:
(Ans = frac{n!y^n}{n^4} sum_{i=1}^n sum_{sum_{j=1}^i a_j = n} frac{prod_{j=1}^i frac{a_j^{a_j}n}{a_j!y}}{i!} = frac{n! y^n}{n^4} [x^n] e^{sum_{j=1}^n frac{j^j n}{j!y}x^j})
多项式(exp)即可。
以上是关于省选前的做题记录(Round2)的主要内容,如果未能解决你的问题,请参考以下文章