Feb
SRM527 Division 1 解题报告
Posted in TopCoder SRM | No Comments »275
题意:要求构建一颗n个节点的树,每个节点的权值为score[dge[i]-1],dge[i]是点i的度数,给定score,问最大权值和是多少?n<=50
分析:所有度数之和为2(n-1),每一个点的dge范围在1到n-1之间。所以DP一下就ok。
450
题意:有一个R*C的01网格,现在给两种描述,描述由"0","1","?"组成,"0"表示这个位置上的数是0,"1"表示这个位置上的数是1,"?"表示这个位置上的数可以是0或1。第一种描述按原网格的顺序给出,第二种描述是打乱了列顺序后的。求一个字典序最小的01网格。R,C<=30
分析:遇到这种字典序最小的问题,一般采取逐位枚举+判断可行性的做法。所以,按从上到下、从左到右的顺序,先尝试填0,判是否可行,如果不行,则这个位置只能填1。
可行性的判断:对于两种描述,可以从第一种描述的各列向第二种描述的各列建立邻接布尔表,布尔表中第i行第j列的元素表示第一种描述的第i列是否可以对应第二种描述的第j列(这里用简单的检查即可)。如果问题可行,则存在一个完备匹配。在逐位枚举的过程中更新布尔表+做二分匹配。
时间复杂度O(N^2*N^3),即O(N^5)。
1050
题意:给出c1,c2,...,cn(ci<=10^18,n<=40),保证c1=1且当i<j的时候,ci|cj。再给一个10^18范围的整数sum。问c1x1+c2x2+...+cnxn=sum的非负整数解的个数,答案取模输出。
分析:这个题,有点难度,想了挺久的。
题解有个背景:一只小兔子从数轴0跳到数轴sum位置,可选步长集合为c[],每次跳跃步长不增加(不超过上一次跳跃步长),求方案数。
分析1. 由于c之间的倍数关系,那么有一个很好的性质,可以帮助我们把sum的规模逐渐缩小:假设第一次跳跃步长为X,那么,2X,3X,4X,……这些都是必经点。
分析2. 设solve(len)(i)(j)表示,跳跃总长为len,可选步长集合为c[1..i],并且最后一步跳跃的步长为c[j]的方案数。那么有solve(A)(i)(k)*solve(B)(k)(j)=solve(A+B)(i)(j),这就是矩阵乘法啦。
由分析1和分析2,可得出,在0到sum之间,c[n]是一个必经点,求出solve(c[n])这个矩阵,并自乘(sum div c[n])次,这样可以把sum的大小缩减为sum mod c[n],继续递归求解。所以问题转化为子问题:求所有solve(len)矩阵,满足len∈c[]。
子问题的求法:总长度为len(设len=c[x]),那么可以一步跳到len处,或者选一个小一点的步长。
当一步跳到len时,有solve(len)(i|i>=x)(x)=1。
当选用小一点的步长时,我们知道,在0到len之间,c[x-1]是一个必经点,根据之前的分析,可以由矩阵solve(c[x-1])自乘(c[x]/c[x-1])次得到。
综上:求解子问题的时间复杂度为O(n^4 * log sum),原问题的时间复杂度为O((n^4+n^3) * log sum)。



