Woj 简易题解 Volume #2

*1101 数据范围太扯淡了。。如果不考虑范围的话可以这样想,从一个点到另外一个点他们的哈密顿距离为他们的最短距离,那么这个距离的步数就是我需要的最少步数,假设从一个点到另外一个点要走m步,那么首先从n个点里选m个出来保证能走到终点,然后这m步的时候水平走和竖直走是独立的,假设需要水平走x,竖直走y,那么这一步的方案数就是从m个点里选x个出来的方案数。然后讨论n-m步无用的步伐,因为已经到了终点,那么接下来走的必然是向左向右,向上向下这样的组合,这里可以首先枚举横着的走了多少,然后对于横着的,用动态规划计算出方案数,同理对于竖直的冗余也可以这么计算,最后相乘累计结果。

1102 很基础的polya的题目,对于旋转,i与n的最大公约数就是置换的长度,对于翻转,n为奇数那么有n种置换,每种置换长度都为n/2+1,如果n为偶数,那么有n/2种置换长度为n/2,有n/2种置换长度为n/2+1。

1103 设f[i]表示当前有i分,赢得游戏的概率,那么显然有f[2] = 1 , f[-2] = 0 , 其余的f[i] = f[i+1]*p + f[i-1] *(1-p),解方程得到f[0]就是答案。

1104 因为总的生命值不超过8W,所以可以考虑背包DP。f[j]表示j点血是否可以构成,t[j]表示构成j点血的人数,那么有转移f[j]=f[j-a[i]],t[j] = t[j-a[i]] +1。对于每一个t[j]的值,如果当前的j满足t[j]和n-t[j]不超过10的话,那么就用j更新一下答案。最后输出结果就可以了。复杂度O(N*80000)。

1105 首先把坐标离散一下,那么我们现在最多有200个坐标了,为一个200*200的网格,然后我们预处理这样一些东西:f[i][j]:从第i行的第一个到第j个有多少个实点。h[i][j]:从第j列的第一行到第i行有多少个实点。use[j][a][b]:从第j列的第a行到第b行,a行b行的第一列到第j列一共有多少个实点。ma[j][a][b]:max(use[j][a][b]...use[m][a][b])。上述的处理均可在O(N3)复杂度内完成。那么对于第j列a到b行为左边边的矩形最多的格子数就为 h[b][j] - h[a-1][j] + ma[j+1][a][b] - f[a][j] - f[b][j] ,枚举j,a,b计算取最大值即可,复杂度O(N3)。

1106 很基本的数位统计,一位位递推就行。

1107 最长公共子序列类型的DP,dp[i][j]表示a串的i位匹配到b串的j位的最大代价,那么dp[i][j]=max(dp[i][j-1] + w[4][b[j]],dp[i-1][j] + w[4][a[i]],dp[i-1][j-1] + w[a[i]][b[j]])。

1108 因为总的数的个数不超过20,所以可以用一个20位的数表示当前的局面,第i位为1表示第i个数存在。对于每个局面,选择一个当前有的数删掉,删掉所有可以用这个数删掉的其他数,可以得到一个新的局面,一个局面为必胜局面,当且仅当他可以到达一个必败局面,一个局面为必败局面,当且仅当他到不了必败局面,然后递归的递推下去,最后看初始局面是必胜局面还是必败局面即可判断。

1109 先把所有的字典串加入到一个集合里。对于每一个询问串,暴力跑出所有通过他一步可以构造出来的串,在字典集合里查询,如果存在就加入答案集合中,最后把答案集合输出。

1110 因为每个字母在四个方向都会出现至少一个,所以我们扫描一遍图可以知道每个字母的矩阵的范围,那么扫描每个字母的矩阵边缘,如果发现这个矩阵中有字母不属于这个矩阵,那么把覆盖的字母到当前字母连一条边,最后构造出来一个字母之间的DAG图,top排序出所有的情况输出即可。

1111 二分切割成的木棍长度,然后计算当前长度可以有多少个木棒来判断如何缩小二分界限,最后把二分出来的木棍长度输出。

1112 并查集的题目,f[i]表示从0到i的奇偶性属于的集合,d[i]表示这个集合中的点i与根节点的同奇偶性关系,如果两个点在一个集合里表示这两个点奇偶性显然为d[i]^d[j]。最开始认为所有的奇偶性都不同,即f[i]=I,对于每一个操作,如果两个点在一个集合里,那么就直接判断这两点奇偶性与c是否相同,否则就合并两个集合,非常好的题目。

*1113 计算几何

1114 根据点到圆心的距离,把分算出来比较下就可以了,水题。

1115 水题,照题意仔细做就行

1116 dp[i][j]表示到了第i个数,最后一个数为j的方法总数,sum[i][j]=sum(dp[i][1]~dp[i][j]),那么有转移 dp[i][j] = sum[i-1][j/2], sum[i][j] = sum[i][j-1] + dp[i][j]。sum[n][m]为答案。

*1117 据说spj有问题?

1118 暴力枚举牌的所有放置方式,判断是否合法,然后更新答案,思维很简单不过代码不是很好写。

*1119 好像要分类讨论什么的很麻烦的样子。。

*1120 这题小情况略多,写了一个然后各种遇到小情况没法处理了,后来xioumu给了一种对于斜着的点判断序号是否连续来决定是否扫描进去的方法,但是总感觉不是很靠谱,有时间再来写。

*1121 完全无思路,求做法。

1122 设f[a][b][c][d][e]表示每行有这么多人的时候的情况,然后转移的话就是每次把a-1,b-1,c-1,d-1,e-1,其他不变来做转移,为了节省空间可以用一个30进制的5位数转成10进制开map来记录状态。

1123 ans=2*n-2,证明比较简单。。N=1的时候要特判

1124 源点和每场比赛连一条流量为2的边,每场比赛和参加这场比赛的人连一条流量为2的边,每个人还有多少分才到第n个人的分数就对这个人到汇点连一条流量为这个差值的边,最后看源点所有边是否都满流就可以了。

1125 反向建图,然后按照编号从小到大开始做dfs,如果一个点没有被之前dfs覆盖到而当前dfs覆盖到了那么其能得到的最小值一定为当前的标号值,否则跳过,复杂度O(N)。

1126 考虑线性筛素数的方法,对于不是素数的数肯定会通过某个素数把其标记为false,那么对于这个数记录下这个素数,这样素数筛完以后我们就有了每个合数的一个约数,然后利用DP的方式,fi[n]可以通过fi[n/a]计算得到。最后把前i个的fi的和预处理一下,询问的时候直接输出就可以了。

1127 其实比较好的做法是把所有点离散一下然后做线段树,当时做的时候脑残了,用了一种很奇葩的方法做的。。我们用一个set存贮所有已占用的区间,那么对于一个插入操作(a,b),我们在已占用集合中用a和b查找,把a和b中间的区间合并成一个大区间,如果a和b之内没有区间,那么就直接插入(a,b),对于删除操作,我们先查找a和b是否属于同一区间,如果是的话那么就把该区间分割成2个小区间,否则就返回无解,这样的话复杂度也是O(NLOGN)的。

1128 直接跑k次矩阵乘法的话必然会TLE,所以需要构造矩阵让K次矩阵乘法后直接能算出总和。设原矩阵为a,a加一列,每一行的值为该行前面所有数的和,a加一行,该行除了最后一列为1外其余均为0,然后求这个矩阵的n次方,得到的结果矩阵中最后一列的前n个值的和就是答案。

*1129 计算几何

1130 对于n,总有一个最小的特殊数,这个数+1~+n均为合数,首先对于每个n先把这个数预处理出来,然后对于每个询问n,以它的特殊数为末状态,暴力向前面递推,来判断0局面为必胜或者必败。递推方法同1108相似。

*1131 No such problem

1132 首先找出8个末状态,然后把123456789到所有状态的答案都预处理出来,每读进来一个状态,就枚举每个末状态,把这个状态按照末状态的1-9转化,直接读出123456789到该状态的答案。

1133 把每个属性前3大的取出来去重,然后从其中(最多9个)暴力选3个出来取max。

1134 把第一个人的排存到一个集合中,对于第二个人的每一张牌,在集合里找一个能覆盖的最大的删去,如果有,答案加一。

*1135 一个点替换两个点总感觉最后图好复杂,还可能有各种环,也不知道怎么判断结束。。

1136 按照原图连边,从garden到Angel跑spfa,松弛公式为d[i]=min(d[i],d[j]*2+need[i])。

1137 显然取最小的是最优的

1138 首先把b次的斐波拉契转移矩阵用矩阵乘法跑出来,然后通过f[g[0]]和转移矩阵跑k次就可以得到最终的结果矩阵了,至于统计和的构造方法可以参见1128。

*1139 计算几何

*1140 计算几何

1141 按照置换的方法套回去就可以了,简单题。

1142 ans[i]=ans[i-1]*2+1,需要大数。

1143 水题

1144 裸的nim游戏,暴力跑出所有局面的sg值,然后把给的几个局面的sg值异或依赖判断是否为0即可。

1145 假设我们已经有了把i个人消息互通的方法数f[i],那么要再加入一个人,那么我们可以先让i+1与i通话,然后让前i个人互通,然后任一个人与i+1通话,即f[i+1]<=f[i]+2。就是说至多两步就可以再添加一个人进去,那么剩下的比较麻烦的一个问题就是能否添加一步就多让一个人加入,这个在n从3到4的时候是成立的(f[3]=3,f[4]=4),问题就转化成了i个人既然能在i步内实现消息互通,那么能否在i-1步内实现i-1个人拥有全部消息,并且一个人只差最后一条消息,因为在n>=4的时候,因为要步数最少,最后一步一定是由互补的两个人通话,且在最后补全最后一个人的时候,最后一个人只有2条消息,所以上述情况不会再发生,即除了n=3是特殊情况外,不会再有特殊情况发生。即在n>=4的时候,f[i] = (i-2)*2。

1146 首先来考虑不能从尾部绕到头的情况,这样是一个很简单的DP,f[i][j][k]表示已经处理完i到j的区间,k=0或者1表示当前磁头停在左端点或者右端点f[i][j][1] = min( f[i][j][1] , min( f[i][j-1][1] + cal(v[j] - v[j-1]) , f[i][j-1][0] + cal(v[j] - v[i] )) ),f[i][j][0] = min( f[i][j][0] , min( f[i+1][j][0] + cal( v[i+1] - v[i] ) , f[i+1][j][1] + cal(v[j] - v[i] )) )。现在再来考虑可以绕回去的问题:有一点是很明确的,就是一个磁头不会绕一整圈再回到开始位置,就是说必然有至少一个点,磁头不会绕过它,那么我们枚举每个点作为区间的开头,按照上述方法做一次DP,取所有方案中的最小值即可。

1147 自然的想法就是暴力所有的方案然后每种方案算一个值出来,问题就是怎么样去判断两个方案是否是一样的,比如1,2和2,1分到一组自然是一种方法,由于冗余的方法数太多,那么直接暴力会导致TLE。我们用一个集合中最大的数来表示这个集合,这样的话我们把数按照从大到小的集合顺序插入,每到一个数,要么把他插入到之前的一个集合里,要么重新开一个集合,只存这个数,最后所有数都插入完了就统计一下答案,更新ans。

1148 f[s][k]表示当前状态为s,最后停在k的最大愉快值,根据当前还能转移的点转移过去即可。

1149 设一辆车能跑的距离为d=k*s/2,那么第一辆车能跑d,再加一辆能跑d/2,再加一辆能跑d/3。。。枚举ans直到跑的距离大于c为止。

1150 由于给的利率是比值,但是股票价格是数值,所以我们首先把股票价格做比换成比值,这样计算就可以放在一起了。F[i][j]表示第i天,手上的股票是j的最大收入,那么我们有转移:f[i][j]=(max(f[i-1][k] * now * 0.99 * 0.99),f[i-1][j]*now)。now表示v[i][j]和v[i-1][j]的比值。但是这样的话转移是M2的,复杂度为200*1000*1000显然无法承受。设l[j]为max(f[i-1][k]),k~0-j,同理r[j]=max(f[i-1][k]),k~j-m,显然l和r是可以在OM预处理出来的,那么对于f[i][j],就有f[i][j]=max(f[i-1][j]*now,max(l[j-1],r[j+1])*now*0.99*0.99),可以在OM内完成转移,总复杂度O(N*M)。

1151 计算出每过一秒时钟和分钟的角度差,然后顺次枚举出第一个合法的即可。

1152 排序后输出第k大的就行

*1153 不知道如何表示局面,求做法。

1154 水题

1155 因为肯定有面值为1的硬币,所以我们首先用最大的去填,不够了用次大的。。。最后用1去填,输出每种硬币的数量即可。水题。

1156 把原图按点双连通分量缩点(注意不是边双连通分量),那么原图成为一棵树,有两种点,一种是关节点,一种是连通分量点,把节点个数大于2的连通分量点标记为黑色,找到起点和终点缩在的树上的节点,查询树上两个节点路径中黑点的数量t,答案为2^t。

1157 累加每个-1左边的1的个数,输出。。

1158 枚举放置国王的线段长和宽,对于长i宽j,其三角形斜边即为我们的线段,我们可以知道线段上有多少个整点,即放置国王的点,也能知道多少个点可以满足相距大于D(设为X),为了不重复计算,我们在线段的开头和结尾各放置上一个国王,那么问题就转化成了,在n个盒子中选m个,首尾必须选,盒子之间相隔至少为X的方法数,就是一个很简单的组合数学问题了。

1159 题意是在图中找一个平均长度最小的环,正确做法是二分环的平均长度,然后把所有的边减去这个长度,然后判断有无正环来确定该平均长度是否存在来确定二分边界如何移动,不过数据好像很弱的样子,我错误的方法居然跑过了= =,就这样吧。。

*1160 计算几何

1161 f[i][j][k]表示构造出0~i层,根节点为j色(0~1),根到叶子的黑点数量为k的方法总数。那么有(1)j=0: f[i][j][k] = f[i-1][1][k] * f[i-1][1][k] - f[i-2][1][k] * f[i-2][1][k] + f[i-1][j][k] ;(2)j=1: f[i][j][k]=( f[i-1][0][k-1] + f[i-1][1][k-1] ) * ( f[i-1][0][k-1] + f[i-1][1][k-1] ) - ( f[i-2][0][k-1] + f[i-2][1][k-1] ) * ( f[i-2][0][k-1] + f[i-2][1][k-1] ) + f[i-1][j][k]。

1162 高精度加法

1163 对于任一种方案,可证最大的牌右边的为递减序列,那么对于每一种f[n]的序列,将牌N-1插入到序列尾,尾-1,尾-2。。。只要满足最大牌后面是递减序列,该序列即为一个合法序列,比如1,2是合法序列,所以1,2,3;1,3,2为合法序列,但3,1,2不是,因为1,2不是递减序列。构造方法也很容易从n推出来。这样,我们就可以从1张排的序列推出n张排的序列了。

1164 没什么技巧,模拟做就是了,也不算很难写。

1165 分解质因数判断就行。

1166 数据范围n不会超过500,枚举所有串的pair暴力判断即可。

1167 bfs扫描有多少个连通块,水题。

1168 简单的模拟题,不过代码不是很容易写简单。

1169 模拟题,没什么说的。

1170 拿个集合存存输出就完了

1171 可别真去死跑了,记忆化一下。

1172 对于一个等式,如果右边是未知,那么左边就未知,注意题目问的是最后哪些变量是未知的,不是中间过程中哪些变量是未知的。

1173 见1070

1174 数据范围很小,纯模拟题。

1175 设f[n]为n朵花时的方法总数,则f[n]=f[0]*f[n-2]+f[2]*f[n-4]+…+f[n-2]*f[0]。递归记忆化什么的随便写了。

1176 也是模拟题,照着处理就是了。

1177 注意到性能参数不会超过100,所以每种物品最多也只用保留100个,每种性能的当然是取价格最低的了。然后就是一个很基本的分组背包,转移略去。

1178 裸的高斯消元,话说谁有判线性方程组一解,多解,无解的模板,我这里只能判一解和非一解。。

*1179 没大看懂题意。。。

*1180 计算几何

*1181 挺老的题目,因为n这一维非常小,所以可以暴力两层的状态一直递推到最后一层去,写不动了。。以后有时间再来写吧。。

*1182 No such problem

*1183 No such problem

1184 就是问n以内因子个数为奇数的数有多少个,题意太扯淡了。

1185 f[i][j]表示把i个球放进j个盒子里的方法总数,若没有空盒子,那么f[i][j]=f[i-j][j](把所有盒子里的球加一个),若有空盒子,不妨让最后一个盒子变成空盒子,f[i][j]=f[i-1][j]。预处理出所有的结果,直接查表即可。

1186 很简单的模拟题,有种比较简单的写法就是沿着0到9扫一圈,如果have[i]!=have[i+1]那么ans+1,最后ans大于2就是NO,否则就是YES

1187 裸的01背包,略。

1188 设sum[i]表示1-i的石油总和,那么有sum[i]-sum[i-1]<=a,sum[i]-sum[i-1]>=0,对于每一组关系a,b,c有sum[b]-sum[a-1]>=c,然后根据差分约束系统建边,跑spfa。

1189 ZOJ风格的题目。。我们所关心的点就是一个起点,终点,和中间的能量点,这些点总共也不超过12个,所以我们首先对于这些点bfs出到其他点的最近距离,这样就得到了一个12个点的图。再来研究我们的方案,一定是从起点,经过某些点,到终点,然后终点到某个点再到终点,终点到某个点再到终点。。。一直到能量够为止,前面一部分是一个很明显的集合DP,后面直接判断剩余点到终点的距离与L的关系就可以了。

*1190 枚举上面话的每个句子,和下面话的每个句子,可以计算出一个权值,那么该问题就成为了一个最优权匹配的问题,可以用KM或者费用流来做(正好两个都不会= =,以后补上吧)。

1191 No such problem

1192 按照题目做就可以了。

*1193 计算几何,据说是Voronoi图?

1194 首先枚举任意两个,计算出其相似值,然后就是一个集合DP了,f[s][i]表示状态为s,最后一个为第i个字符串的最大值,那么f[s+2^k][j]=max(f[s+2^k][j],f[s][i]+val[i][j])(if ( s &(2^k)==0));

1195 注意到只有两行,那么可以用f[i][j]表示第一行到i,第二行到j的状态总数,因为i和j相差超过2是没有意义的(因为超过2的话短的那行一定只能用1*2插入进去,所以可以简化状态f[i][j]表示下面一行到i,上面一行与其相差j的方法总数(-2<=j<=2),转移方程应该很好推的,略去。

1196 从大往小找,最大的数没有比他小的,所以他右边有几个比他小的就是第多少个+1个数,然后从序列中把这个数删除,继续找现在的最大的,因为n=8000,直接跑N2可能会超时,需要用一颗线段树来维护。

1197 强连通分量缩点,然后看原图是否存在一条n个点的链,如果有的话就是YES,否则NO,至于判断是否存在长为n的链的方法,就把原图进行TOP排序,然后看TOP序列中相邻两个点是否有边相连即可。

1198 集合DP,略。

1199 f[k][i][j]表示第k步的时候一个脚在i一个脚在j的最小体力消耗,方程转移较简单略去。

1200 强连通分量缩点,然后直接输出连通分量数量。

     感觉第二版满满的都是集合DP和博弈啊,还都是暴力的博弈啊,需要集合DP的博弈啊,好深的怨念。。

     要程序的可以私下联系。。。

你可能感兴趣的:(Woj 简易题解 Volume #2)