Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

时间:2021-01-09 07:41:47

据说做TC题有助于提高知识水平? :)

传送门:https://284914869.github.io/AEoj/index.html

转载请注明链接:http://www.cnblogs.com/Blog-of-Eden/p/8407296.html

Topcoder SRM 562 Div 1 - Problem 1000 InducedSubgraphs

当K*2<=N的时候,显而易见的是编号为i(K<=i<=N-K+1)的点一定会形成一条链。

枚举合法的这样的链,剩下的暴力dp吧。

当K*2>N的时候,显而易见的是编号为i(N-K+1<=i<=K)的点一定会形成一个联通快。

如果把这个联通块去掉,树会形成若干个不相交、不接触的小联通块,且这些联通块的大小之和一定。

如果把树的一个点提根,进行上下dp,就能很方便地进行统计答案。

Topcoder SRM 563 Div 1 - Problem 950 CoinsGame

好惨惨啊!这么简单的题竟然没有自己想出来~~

我们称棋子A和棋子B等价,当且仅当它们只会同时在这个棋盘上,或同时离开棋盘。

一个显然的结论就是,若A和B等价,B和C等价,那么A和C等价(即具有传递性)

所以可以通过bfs求出所有等价点对,通过并查集合并。用总情况数减去不合法情况数就好了。

Topcoder SRM 564 Div 1 - Problem 850 DefectiveAddition

topcoder罕见的水题啊!

如果我们已知了每个数相与原数不同的最高的二进制位,(设ta为pi)

那么对于第k位,如果有x个数满足pi>k,由于这些位的异或值确定,

所以,当x>0时,有2^(x-1)种方案。

由于当x=0时会有意想不到的事情发生,所以稍微dp一下就好了。

Topcoder SRM 565 Div 1 - Problem 1000 UnknownTree

topcoder罕见的无思维难度码农题。。

分两种情况讨论:A、B、C在同一条链上。以及A、B、C不在同一条链上。

Topcoder SRM 566 Div 1 - Problem 1000 FencingPenguins

http://www.cnblogs.com/Blog-of-Eden/p/7852426.html

Topcoder SRM 567 Div 1 - Problem 1000 Mountains

一道很妙的题哇。

一个显而易见的结论是,一座山的可见范围,一定是一段连续的区间。

考虑编号从大到小的放置山。

如果当前山可见,并且可见范围不是从最左边到最右边。

那么又有一个很显然的结论,当前山只有两个合法位置。

考虑如果当前山不可见,那么这座山对之后要放的山没有丝毫影响。直接乘上这座山合法的位置数即可。

如果这座山到处都可见?这是个较严重的问题,

我们考虑,把所有这样的到处都可见的山全部拿出来。(按照编号从小到大)(我们称之为大山)

相邻两座大山之间夹着若干个小山。

对于大山L和大山R,(L<R),很显然1到L-1和R+1到n的山对这之间的山的放置没有影响。

所以可以枚举相邻两个大山的位置,对之间的小山位置进行dfs。

dfs的复杂度是2的幂次,可以接受。

Topcoder SRM 568 Div 1 - Problem 1000 DisjointSemicircles

异常兴奋!又一道喜闻乐见的分情况讨论题!

我们设有m对连线已经确定。(m<=n)

当m比较大的时候,暴力似乎行。O(2^(2n-2m-1)*C(2n-2m,n-m))

当m比较小的时候,枚举这些连线分别在上方还是在下方。

方案合法当且仅当这个半圆里面与它同向的点的数量是偶数。

设向上为1,向下为0,一个半圆相当于限制了这个半圆之中的变量的xor值为1或者是0.

对于前缀xor数组,相当于限制了两个位置上的数xor为1或者是0。

这个用并查集来检查一下是否合法即可。

Topcoder SRM 569 Div 1 - Problem 1000 MegaFactorial

我真是个爱学习的孩子,在秋游的时候还在想这道题~~

简单来说,由于B<=10,我们只关心的是B的最小质因子p以及它的指数q。

简单的说,我们只要统计N!K的值中,质因子p的指数Q,计算Q div q就好了。

由于对1e9+7取模,div比较麻烦,所以:Q div q = (Q - Q mod q) / q

再由于K比较小,所以矩乘一下就行了。

Topcoder SRM 570 Div 1 - Problem 900 CurvyonRails

谁来治一治我普及组级别的网络流水平啊o(╥﹏╥)o

复杂地来说,黑白染色,每个格子拆成两类点:横方向点和纵方向点,

由于两份流量都流入横方向点或都流入纵方向点都会产生1的费用,

所以将方向点拆点,连两条边,一条流量为1,费用为0;另一条流量为1,费用为1。

Topcoder SRM 571 Div 1 - Problem 1000 CandyOnDisk

Topcoder也会出这种无脑题?

若a能到达b,那么b也能到达a。

如果从一个圆到达另一个圆,其可到达范围是两个圆环。

每个圆环当作一个点,就可以建图跑spfa。

需要特判一些特殊情况(*/ω\*)

Topcoder SRM 572 Div 1 - Problem 1000 NextAndPrev

枚举分界点,贪心求最小代价就行了?

由于口胡我可能没想清细节。。

Topcoder SRM 573 Div 1 - Problem 850 WolfPack

以我的智商看来是做不动这种脑洞题啊。

每次x可以+1,-1,不变,y也可以+1,-1,不变,且x,y至少有一个变,这个很烦啊。

根据题解的做法,我们把坐标轴旋转45°,题目变成了:

每次x可以+1或-1,y也可以+1或-1,且x,y独立!这一步转化好妙啊!

接下来就好做了,对于一个终点Z,

对于Zx,可以求出x方向上的方案数;对于Zy,可以求出y方向上的方案数。

答案是sigma Zx,Zy [Fx(Zx)*Fy(Zy)] = sigmaZx[Fx(Zx)] * sigmaZy[Fy(Zy)]

TopCoder SRM 574 Div 1 - Problem 1050 Tunnels

对于给出矩形中的非从左边连到右边的地道,这些地道会形成括号序列,

对于从左边穿到右边的地道,可能是从左往右,也可能是从右往左?

从上往下进行dp?

似乎怎么想也想不清啊。。反正是口胡,放弃思考了。。

TopCoder SRM 575 Div 1 - Problem 1000 Tunnels

每次想网络流题都要想好久好久~~。。

先进行黑白染色,由于L字形角落的格子一定黑色,两端的格子一定白色,

两端的格子,一定有一个在奇数行,一个在偶数行。

源点流向奇数行,偶数行流向汇点就行了。

TopCoder SRM 576 Div 1 - Problem 900 CharacterBoard

Topcoder罕见的放松题啊。

我们考虑给你的矩阵中两个元素x和y,若它们在字符串中的位置相同才可能发生冲突。

位置相同当且仅当x和y的位置差能被Len整除,这样的len最多只有i0*j0*sqrt(i0*W)种

对于这样的每一种len,暴力判断是否合法以及计算方案数,

如果不存在这样的冲突,方案数为26^(Len - i0*j0)。所以等比数列求和即可。

TopCoder SRM 577 Div 1 - Problem 1000 BoardPainting

又是网络流。┭┮﹏┭┮

好难哇,怎么做啊。。

在此给出周欣的算法:

如果把相邻两个格子之间新建一个虚点,选择这个虚点,就表示这两个格子在一次染色中完成。

由于染色过程不能转弯,这限制了一个格子横放向上的虚点和纵方向上的虚点不能同时选。

这就是二分图最大独立集问题,可以用网络流解决

TopCoder SRM 578 Div 1 - Problem 1000 DeerInZooDivOne

看到题目描述中的鹿角,莫名想到乔巴~~

简单地说,可以枚举两个联通块之间的分界边,然后进行dp,

考虑f[a][b]表示以a为根节点,b为根节点,a联通块与b联通块同构的最大大小。

a的若干个儿子和b的若干个儿子一一匹配,其f值的和+1就是f[a][b]。

这就是二分图最大权匹配

TopCoder SRM 579 Div 1 - Problem 1000 RockPaperScissors

如果当前我们知道了对手之前扔出a个剪刀,b个石头,c个布,我们可以通过dp预处理求出下一次对手扔剪刀、扔石头、扔布的概率。

然后我们当前做出最优决策,使这一回合的期望得分尽可能的大。这也是一个dp。

TopCoder SRM 580 Div 1 - Problem 1000 WallGameDiv1

简单博弈,我们可以证明,Rabbit不会将棋子向上移,

当Rabbit在某一行,且下方有障碍时,Eel不会放障碍,

以此我们得出一个结论,Rabbit在一行中的运动是,左,右,左,右,左,......最后下。

我们还可以得出一个结论,当Rabbit在某一行某一列上,且此时Eel没有在它下方放上障碍,那么Rabbit也一定会往下走了(往左右走之后还一定会回到这里)。

所以可以用区间dp。f[i][L][R][0 or 1]表示第i行,已经放了L到R的障碍(即Rabbit已经走过了L到R),此时Rabbit在L-1还是在R+1。

每次Eel决定Rabbit下方是否有障碍,如果有障碍,则Rabbit决定往左或往右。

据说cwy用奥妙重重的骗分方法A了此题?说不定那也是对的喔。。

TopCoder SRM 581 Div 1 - Problem 900 YetAnotherBoardGame

据说暴力的复杂度是对的??

如果当前行之前的行已经确定,当前行的上一行中有一些还是白色,

它限制了当前行的某些列必须进行操作,其他列必须不操作。

对于这些列,如果以前有过操作,那么当前的操作种类已经确定。否则当前有两种选择:操作1和操作2。

复杂度证明:

假设有m列进行过操作。每一列最多会产生一次两种选择,复杂度2^m。

由于m列是在M列中选择的。枚举子集中的子集复杂度是3^M。

TopCoder SRM 582 Div 1 - Problem 1000 SemiPerfectPower

参考了VFK的题解(http://vfleaking.blog.163.com/blog/static/174807634201352023221271/)

好妙的数论题哇。

首先我们发现只要计算b=2和b=3的半完美数即可。因为b>3的半完美数都可以用b=2或3来表示。

假设P2(x)表示x中不含平方因子。P3(x)表示x中不含立方因子

我们可以用P2(x)表示b=2的结果,P3(x)表示b=3的结果。

最后一步就是求出可以用b=3表示,但不能用b=2表示的半完美数的个数。

如果能表示成b*y^3(且P3(b)=True)。那么b*y^3 = (b*y) * y^2

再假设k^2|(b*y),且P2(b*y/(k^2))=True(即k^2是b*y的最大的平方因子)

那么可以表示成:b*y/(k^2) * (y*k)^2。所以b*y/(k^2) >= (y*k),即b>=k^3

初步列出式子:

Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

我们发现,这个P2(b*y/k^2)不太好处理。

所以企图把它拆掉。

设k' = k^2 / gcd(k^2,b);

b' = b / gcd(k^2,b);

y' = y / k';

P2(b*y/k^2) = P2(b'*y/k') = P2(b' * y') = (P2(b') * P2(y')) AND (gcd(b',y')==1)

我们成功地把它拆掉了。再转化一下式子:

Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

我们发现这个gcd很烦,我们用莫比乌斯反演解决:

Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

我们可以预处理最后面那个sigma。前面的复杂度是n^(1/3)*log(n)*log(n)。

TopCoder SRM 583 Div 1 - Problem 950 RandomPaintingOnABoard

期望回合数等于每一回合进行的概率之和。

如果第i回合进行,说明前i-1回合没有实现每行每列至少一黑。

我们可以行集合和列集合,如果之前每一回合都在这之中选,那么当前回合就会进行。这样的概率是(sigma x)^(i-1) / S^(i-1)

由于这样枚举可能重复,所以容斥一下即可。根据行集合+列集合的大小的奇偶性来判断+-符号。

这样可以算出第i回合进行的概率。

但是对于每一个i,都要计算,这很麻烦。我们发现i只出现在指数上,而枚举的i是从1到无限大。所以可以用无穷长的等比数列求和公式来计算。

这样我们得到了一个优秀的2^(n+m)的算法。我们发现数据范围n*m<=150(很小?)

我信心满满地写了一个,样例都Tle了。。

怎么办呢?我们还漏了一个条件:每个格子上的数是0到9范围。。

所以我们发现这个公式中底数的范围只有0到3600,所以有很多项是重复的。对底数进行dp即可。

TopCoder SRM 584 Div 1 - Problem 900 FoxTheLinguist

我们可以轻松建图,只要求一个有向图最小生成树就可以了。

据说可以用朱刘算法?

我不会啊QAQ

TopCoder SRM 585 Div 1 - Problem 1000 EnclosingTriangle

我们枚举三角形的一个顶点,如果已知第二个顶点,第三个顶点有一个可行区间。

已知随着第二个顶点的顺时针移动,第三个定点的可行区间是单调的。

再由于只有20个点,所以可以先预处理20个点的凸包,可能还要预处理可行区间左端点的前缀和数组,

可能差不多就做好了吧。。

TopCoder SRM 586 Div 1 - Problem 1000 StringWeight

显然,若字符串长L,那么这个轻的字符串满足有min(26,L)种字符,且相同字符挨在一起。

显然就可以dp了,f[i][j][k]表示前i个字符串已经完毕,出现j种不同字符,其中有k种字符今后还要再出现,的最小重量。

考虑当前字符串,我们已知了字符种数,

其中有一些连接了之前的字符,并且之后还要出现,它对重量的贡献是L;

有一些连接了之前的字符,之后不会出现,它对重量的贡献是前缀长度;

有一些是新出现的字符,但之后不会出现,它对重量的贡献是它在这个字符串中的长度;

有一些是新出现的字符,之后还要出现,那么它对重量的贡献是后缀长度。

根据一定的贪心结论,前缀长度越短越好,后缀长度越短越好。那么上述第一种字符和第三种字符一定排在中间。

一个很显然O(n*26^5)的dp就出来了。

再根据一定的贪心结论,第一种字符变成第二种,同时第三种字符变成第四种,这样一定更优,

所以复杂度变成O(n*26^4)

TopCoder SRM 587 Div 1 - Problem  900 ThreeColorability

被题解的做法深深地震撼到了。。

考虑2*2的方格,一定全N或全Z,或两个N,两个Z。

推广到n*m,任意2*2方格满足这个条件,就一定能被三染色。

分析这个条件,设N=0,Z=1,我们发现相邻两行要么完全相同,要么完全相反。相邻两列也是一样。

所以我们可以构造h[i]数组,构造g[i]数组来表示整个能被三染色的矩阵,矩阵中cells[i][j] = h[i] xor g[j]。

任意的h,g数组对应一个合法矩阵。而输入的'N'或'Z'限制了h[i] xor g[j]的值。

所以可以进行二分图染色。再因为要字典序最小,所以染色的时候可以贪心。

TopCoder SRM 588 Div 1 - Problem  1100 GameInDarknessDiv1

冷静分析一下,这道题非常有意思,

考虑现在Alice到达一个点,这个点提根后有多个子树,且Bob可能存在于这些多个子树中。

考虑若子树a大小<=2,那么Alice可以进入a一步,去清除Bob存在于该子树的可能,然后回到根。

这样,Bob无法从一个子树飞往另一个子树。

而如果子树a大小>2,Alice进入a会到根至少需要4步,用这段时间Bob可能飞到其他各个子树中。对Alice极为不利。

所以我们来分析Alice的策略:

只有1个子树a大小>2:进入a,清除Bob在a的可能性,之后依次清楚其他子树。

只有2个子树a、b大小>2:进入a,清除Bob在a的可能性,之后清除除a,除b以外其他子树,最后清除b。

有3个子树a、b、c大小>2:凉凉。。Bob无论何时都有可能在两个大小>2的子树中。

所以我们得到了Bob的策略,在不被Alice抓到的同时,走到一个节点,使得这个节点提根后有至少3个子树大小>2

我们也得到了Alice的策略,不让Bob的计谋得逞。。

所以,当存在一个点 P ,满足 dis(A,P)>=dis(B,P)+2,且以 P 为根时有至少 3 个子树的深度大于等于 3 时,Bob 胜,否则 Alice 胜。

TopCoder SRM 589 Div 1 - Problem  900 FlippingBitsDiv1

按M>sqrt(N)或M<sqrt(N)分情况讨论即可。

TopCoder SRM 590 Div 1 - Problem  1000 FoxAndCity

这是道较为有趣的题,

我们发现,a[i]数组合法的充要条件是

a[1]=0,若i>0,则a[i]>0。且如果i,j相连,那么abs(a[i]-a[j])<=1。

有了这个结论之后,我们把每个点都拆成n个点,第k个点和第k+1个点连通表示当前这个点的权值a至少为k。

很容易建出网络流模型,跑一遍最小割即可。

TopCoder SRM 591 Div 1 - Problem  900 StringPath

一句话题解:轮廓线动态规划(状压dp)

TopCoder SRM 592 Div 1 - Problem  1000 SplittingFoxes2

DFT(a) = DFT(p) * DFT(p),已知a,求p。

p = DFT^(-1)( sqrt(DFT(a)) )

由于sqrt的时候,每一项有正负两种值,需要枚举。

因为p关于0对称,所以只要枚举2^(n/2)种情况即可。

(据说还可以用NTT来排除精度误差?)

TopCoder SRM 593 Div 1 - Problem  1000 WolfDelaymasterHard

暴力dp是O(n^2)的。很容易发现当右端点为i时,左端点j可行的取值区间只有不超过log(n)段。

这样很容易实现O(nlogn)复杂度的dp.

题解给了一个优秀的O(n)做法。

我们考虑,如果一个区间的左边一半全是问号,左端点为i,右端点j可行的取值区间只有一个。

若一个区间左边一半至少有一个'w',右端点为i,左端点j可行的取值区间也只有一个。

前者从当前dp值对之后一段区间的dp值有贡献,可以前缀和优化。

后者前面一段区间的dp值对当前dp值有贡献,也可以前缀和优化。

TopCoder SRM 594 Div 1 - Problem  950 FoxAndAvatar

非常有趣的题哇

很容易发现:答案<=4

又很容易发现,每次取走一块矩形的时候,对局面有影响的只有两个值:比x小的数中被取走了多少个数,比x大的数中被取走了多少个数。

我们设比x小的数中被取走了p个,比x大的数中被取走了q个。

很容易证明,p是定值的时候,q越大越好。

所以我们可以进行DFS!

每次DFS,枚举p的值,O(1)求出当前状态下,q的最大值。

很容易发现,DFS只要枚举两层。在第三层我们O(1)判断是否可以一次性取完只剩x,否则答案就是4。

复杂度O(n^2)。

TopCoder SRM 595 Div 1 - Problem  900 Constellation

根据经典套路,一个凸包的面积是凸包上相邻两个点与原点形成的向量的叉积的和的1/2

只要计算任意两个点,成为凸包上相邻两个点的概率,就可以计算它们对期望答案的贡献。

即这两个点所在直线的一侧没有点。

TopCoder SRM 596 Div 1 - Problem  1000 SparseFactorial

若F(x)%m=0,则F(x+m)%m=0

所以我们可以对于所有x%m的余数,求出x至少是多少才满足F(x)%m=0

先对m分解质因数:m=p1^k1*p2^k2...*pn^kn

求出最小的x,使得x%m=x',F(x)%(pi^ki)=0。(可以对于所有的pi,求出对应的最小x,然后取其max即可。)

存在(x-j^2)%pi=0

存在j^2 %pi = x % pi

预处理x所对应的可能的j%pi。

所以,我们可以暴力地从小到大枚举所有可能的j,再求出所对应的比j^2大的x,判断F(x)分解质因数后是否有ki个pi。

由于ki很小(log级别)!所以复杂度是对的

TopCoder SRM 597 Div 1 - Problem  900 LittleElephantAndBoard

我们考虑,在原来2*M的表格下面,再添一行,变成3*M的表格。

对于每一列,由于相邻两个颜色不一样,我们把第三行的那个格子颜色涂成与前两行颜色不同的第三种颜色。

由于每种颜色在任意一个2*2矩阵中至少出现了一次,所以第三行中相邻两个格子颜色也不同。

以上,题意转化为了M-R个红球,M-G个绿球,M-B个蓝球排在同一行,相邻两个颜色不同的方案数。

紧接着我们发现,相邻两个蓝球之间,红绿球必然交替出现。当长度为偶数时,红绿个数相同。当长度为奇数时红比绿多一球,或反之。

于是,枚举长度为奇数的段数,由M-R和M-G可知其中有多少段红比绿多一。接着就可以直接用组合数计算了。

TopCoder SRM 598 Div 1 - Problem  950 TPS

感觉是很显然的树形dp?

如果p的两个儿子a,b,a,b的子树内都没有信标,那么a,b内相同深度的点无法区分。

用这一性质进行树形dp

TopCoder SRM 599 Div 1 - Problem  950 SimilarNames

我们先把trie树建出来。要求给trie中字符串结尾的节点标号0到n-1,使得满足性质。

于是树形dp的想法就出来了。

然而限制涉及到的点数有8*2=16个,要开2^16的状态。暴力3^16转移复杂度不可观。

注意其实转移的时候枚举的很多次子集都是没有用的。

我们假设dp时要枚举子集a,枚举子集b。然后把a、b合并起来。

对于一条限制s是t的前缀,显然s不能单独出现在a或b中,同时子集a和子集b不能有交。

对于这一种限制,

a:空, b:空;a:t, b:空;a:空, b:t;a:空, b:{s,t};a:{s,t}, b:空。 有最多5种转移。

所以总复杂度为5^8*50。(我们需要先预处理这些可能的子集转移)

————————————————华丽的分割线—————————————————

到此为止,SRM562到SRM599的题就结束了。

再宣传一下传送门^_^

https://284914869.github.io/AEoj/index.html