05 2013 档案
摘要:题意:转化后为给定一个数L,问L拆成N个不同的数相加的方案数,其中N>=2。解法:其实和上次做的分解的2的幂的数量相同,由于要求每个数都不相同,这里有一个非常好的观察角度,那就是观察一个数的分解中是否存在1,再加上考虑其能够被分解的数的个数即可建立递推关系。设f[i][j]表示数 i 被分成 j 个不同的数相加的方案数,那么考虑最后分解中不含有1,那么这部分由f[i-j][j]得到,因为后者的每一个分解出来的数都加上1就行了;接着考虑分解中含有1,那么可以假定这个1就是最后分出来的,因为分解的顺序并不影响最后的结果,由于分解中数均不相同,扣除1后,就变成了f[i-1][j-1]中不含有1
阅读全文
摘要:题意:给定若干根长度为Li的绳子,现在每条绳子只能够切成两份或者不切,问最后最多产生多少根长度相等的绳子?解法:首先明确一定就是每条绳子最多对结果贡献2,因为一条绳子最多切成两份,且当最后结果为其长度的一半时才成立,其余绳子要么贡献为0(长度小于枚举长度),要么贡献为1(长度大于枚举长度不等于2倍的枚举长度)。因此可以枚举这个所切的长度,很容易推出这个长度一定会是某个绳长的一半,由于绳子的长度可能会出现奇数,因此给所有的长度乘以2之后再枚举每条绳子的一半就可以了,使用树状数组初始化前缀和,如果枚举的长度为Lx最后的结果为长度为Lx到MaxL的数量加上长度为2*Lx的绳子数。代码如下:#incl
阅读全文
摘要:题意:给定一个很优美的三角形,问从第1层走到第N层的走法有多少种?解法:由于每一层能够向左右行走到任意位置再向下走,所以设f[i]为从第一层到第 i 层的方案数,则有递推关系f[i] = f[i-1] * 2 * i。由于最后的结果是对1000003取余,所以1000003之后的结果一定都为零。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>#include <set>using
阅读全文
摘要:题意:三维子矩阵最大和。解法:枚举三维的平面两维,然后将第三维转化为线性求解,时间复杂度O(n^5),这题被读入数据方位坑了,绝对值不超过2^31,负数没有问题,int形最大正整数是2^31-1...... 导致一直WA,欲哭无泪。代码如下:#include <cstdlib>#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;typedef long long LL;const LL INF = 1
阅读全文
摘要:题意:给定N个三维平面点,每个点都有一个高度,每两个点之间的需要构边,边的距离由x,y坐标的欧几里得距离确定,边的花费有点的高度差即z值确定,现在问一个合理的生成树中,花费比上距离的最小值为多少?解法:每一条边对应于一个高度差,设每条边的高度差为Hi,距离为Li,则要求找到一组边集满足,一如既往的,我们假设一个比例R使得有成立,那么对式子变形后有,得到这个式子后,我们就能够将边权进行修改,求一个最小生成树来判定是否满足<=0的要求。由于图是一个稠密图,所以kruskal算法超时了,改成prim后,priority_queue照样超时,最后改成最普通版的才Ac掉。代码如下:#include
阅读全文
摘要:题意:给定一个点,一个圆,以及一个矩形,现在问从一个点到一个圆再到一个矩形的最短距离为多少?到达一个目标可以只挨着或者穿过它。解法:目前只知道从一个点到圆上按照[0,PI],[PI,2*PI]的两个半圆进行划分确实是满足距离是一个凹函数,但是加上到矩形的距离后仍然满足三分性质则不知道怎么得到的。具体做法是先将整个坐标系平移使得圆心落在(0, 0)处,然后三分枚举圆上的点,距离由两部分组成,一部分是点到圆上点的距离,一部分是点到矩形的距离,后者转化为点到四条线段的距离求解。代码如下:#include <cstdlib>#include <cstring>#include
阅读全文
摘要:题意:问给定的一张图中,相距最远最远的两个点的距离为多少。解法:直接对每一顶点搜索一遍即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>#include <string>#include <map>using namespace std;int N, M;const int INF = 0x3f3f3f3f;map<string,int>mp;stru
阅读全文
摘要:题意:要求计算两个和值比较大小。注意没有马或者是炮的时候能量减1,且能量不能小于1。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;int table[10] = {16, 7, 8, 1, 1, 2, 3};int main() { int T; scanf("%d", &T); while (T--) { int x,
阅读全文
摘要:题意:一个裸的枚举题,告诉你M个点,问这M个点能否覆盖其他非M点。做的时候时间复杂度计算错误。。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int N, M;int r[15];int x[15], y[15];char mp[55][55];char tp[55][55];const int INF = 0x3f3f3f3f;bool judge
阅读全文
摘要:题意:就是最小生成树,题中给定了一条必须要连接的边,排序的时候不把他考虑进去即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>#include <cmath>using namespace std;int N;struct Point { int x, y;};struct Edge { int a, b; double dis; bool operator < (co
阅读全文
摘要:题意:给定一个整数串,有Q组询问,问这个串中长度为w的子串中不同的数字之和为多少,这题的动态规划感觉很有技巧性。解法:设f[i]表示w为 i 时不同的数字之和,那么考虑f[i+1]和f[i]的关系可以得知:f[i+1]就是从f[i]中去除最后一个子串后在每个串后加上一个数字的情况,因此可以得到这样的一个递推式:f[i] = f[i-1] - tail[N-i+2] + left 其中tail[N-i+2]表示长度为i-1的最后一个子串中不同的数字共有多少个,left表示所有数字中与前一个相同数字的长度大于 i 的数字还剩多少个。因此还要另外预处理出后缀不相同数字个数,和最近相同数字的长度,注.
阅读全文
摘要:http://www.cnblogs.com/skyiv/archive/2010/03/27/1698550.html关键点在于通过记录一个数被分解的方案中包不包含1来考虑。得出结论有:f[2*N+1] = f[2*N]f[2*N] = f[2*N-1] + f[N]f[2*N] = f[0]+f[1]+...+f[N]代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>using names
阅读全文
摘要:题意:给定一个矩阵,矩阵上的每一点都有一个值。每次能够从任意一点开始,任意一点结束,每到一个点交替的加人的水平和剑的水平。问一共有多少种方法使得人的水平和剑的水平在最后相等。解法:f[x][y][k][0]表示在xy位置人的水平减去剑的水平的差值为k且该位置走奇数步的情况有多少种f[x][y][k][1]表示在xy位置人的水平减去剑的水平的差值为k且该位置走偶数步的情况有多少种然后维护这个数组就可以了,有一种省略了最后那个0、1的写法现在还搞不大清楚。代码如下:#include <cstdlib>#include <cstdio>#include <cstring
阅读全文
摘要:题意:给定N个点,M条单向边,问在图中寻找一条回路,使得该路径上的所有点权和除以边权和最大。解法:设某点点权为ai, 边权为bi。选择某点的同时就意味着选择了某条边,那么我们把这条单向边划给弧头,因此可以得到表达式,s是牛选择的出发点。可以利用01分数规划的一般解法来求解,那就是选择某个比例进行合法性判定,如果这个比例能够达到,则把比例加大,如果不能的话,缩小这个比例,所以也叫做参数搜索,假设这个比例为R后,上式变为是否成立的判定问题。由于一个图中的某条回路小于0可以用spfa进行判定,那么我们就可以得到一个非常接近正确答案的值,只要精度够高,就能够保证得到的答案取两位后能够与等于0的参数R相
阅读全文
摘要:这次真的很挫,写了三题竟然只过了一题,cf的数据强是一方面,再者也发现自己写代码时的一些细节部分没有注意,过来改了昨天两天代码都很快AC了。A.Strange Addition这题只需要处理几种情况就可以了,100和0必须取,其他如果同时出现X0和X这样的数就取两个,否则XX、X、X0取中间任意一个。代码如下:#include <iostream>#include <cmath>#include <cstring>#include <cstdio>#include <string>#include <stdlib.h>#i
阅读全文
摘要:题意:给定一棵树,然后给定若干组询问,问某些点被作为最近公共祖先的次数。解法:刚刚一直不知道根在哪里给了出来,后来才发现给定的点一定是按照从层数低的节点指向层数高的节点,因此没有双亲的节点为根节点,然后运行tarjan算法即可。这里刚开始的时候我还想把最后的结果除以2输出,这里没有这个必要,因为两个节点一定有一个先后的遍历顺序,这个顺序保证了只被统计一次。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostre
阅读全文
摘要:题意:给定N个节点一棵树,现在要求询问任意两点之间的简单路径的距离,其实也就是最短路径距离。解法:spfa:直接对每一对点作一次spfa即可。Tarjan:求出两个点A,B之间的最近公共祖先C,设根到每个点的最短距离为dis[],那么距离就是dis[A]+dis[B]-2*dis[C]。而根到各个点的距离一次dfs就出来了,因此问题转化为求出两点之间的最近公共祖先,Tarjan算法能够离线解决所询问的点对。原理如下:对于一次dfs,当第一次遍历到点u时,那么令set[u] = u。遍历完以u为根的树后,将u所属集合指向双亲节点。接下来查看u的访问列表中有没有询问<u, v>的点对,
阅读全文
摘要:题意:给定一棵树,每个节点刚开始的时候都是黑色的,现在有Q组操作,要么是询问当前的树中距离最远的两个黑色的距离是多大,要么是改变某一点的颜色。解法:该题看论文+参考代码搞了一天,感觉模型的转化已经求解的过程都非常的巧妙。1.将这棵树有树形结构选择一个根节点再通过dfs搜索转化线性结构,然后将距离问题用括号来描述。2.使用括号描述后,发现任意两个点的距离是通过对之间的括号序列进行某种消除从非稳定态到达一个稳定态,然后在稳定态中得到距离信息。3.发现括号序列是能够进行合并的,所以线段树被派上了用场。而这明显又是一个动态规划的合并过程,关于区间的线段树题无非要维护这么几个量,单独的区间、左连续的区间
阅读全文
摘要:题意:存在一个固定编号[1,10^9]的盒子群,每个盒子里面都有一个数Ai(Ai>=0),刚开始的时候不知道各个盒子里面的数是多大。有Q组更新,分别表示[Li, Ri]内最小的元素是多大,现在问Q组操作后,盒子中数字总和最小可以为多少?解法:标准题解是并查集树状数组的解法,谢勇教练也提到可以使用线段树来解。这里就是使用的线段树来求解。由于该题需要离散化点,这里有个地方特别要注意就是不能够建一棵点树,因为如果建立了一棵点树,那么意味着离散化后的叶子区间是单个点,各个相邻的叶子节点之间的区间信息无法保存,也就是这里错了很多次。正确的做法是如果有某组更新是[Li, Ri] Ci,那么就是更新[
阅读全文
摘要:题意:给定一个N个不同的非负整数(每个数不大于10^6),1<=N<=5000,问找到一个最小的m使得N个数去掉最多x(0<=x<k)个数后能够使得N-x个数%m两两不同。解法:首先可以给定出一个暴力的方法,那就是枚举所有的m,从1开始,然后统计余数相同的数一共多出来多少个,很明显,当多出来的数大于k时则不满足情况,从小到大枚举m遇到第一个满足要求的返回即可。但是这样很显然会超时,时间复杂度为O(N*10^6),这里有一个优化如下:统计出所有的两两组合差值的情况,如有两个数x,y如果x % m = y %m,那么(x - y) % m = 0,统计差值将在后面的计算中发
阅读全文
摘要:题意:给定一个n*n的矩形框,也就是限制在一个(0,0)到(n,m)的平面区域内,求出一个最大的矩形,该矩形面积要求最大,且长和宽的比要为a/b,并且该矩形需包含一个限制区域内的一个点,该矩形的中心应该离这个点越近越好。输出左下角和右上角的坐标。如果在满足所有要求的情况相同近的话输出坐标字典序最小的一种情况。解法:初读起来,这题的限制条件颇多,做的过程中确实有许多地方需要注意,那么我们来一步步解决这个问题:1.首先假设这个矩形的的长(投影到x轴上的量)为sl, 宽为sw(投影到y轴上的量)。那么依据题意有sl / sw = a / b。将方程变形有b*sl - a*sw = 0的形式,可以用一
阅读全文
摘要:题意:要求给出一个数N的余数系的三个排列A, B, C,其中使得对于任意的 i 满足(A[i] + B[i]) % N = C[i]。例如N=5的时候有一下排列:A: 1 4 3 2 0B: 1 0 2 4 3C: 2 4 0 1 3解法:首先排列如果存在的话,肯定是不唯一的,因为可以随意交换A,B,C的相同两列使得结果仍然满足。对于一个给定的N,我们可以列出一下一张图:横纵坐标反应了余数相加的情况:0 1 2 3 41 2 3 4 02 3 4 0 13 4 0 1 24 0 1 2 3只要取从左上到右下的对角线即可。以上只能够保证N为奇数的时候有解,不足以说明白偶数为何无解。还有一种观点现
阅读全文
摘要:题意:给定了一个塔防的游戏模型,跟着这个模型进行模拟,输出能在多少时间内消灭掉所有的怪兽,如果不能的话,输出-1。解法:这里提几个要注意的地方:1.注意怪兽不要走回头路;2.注意已死的怪兽不能够再次成为防御塔选择或者是移动的对象;3.所有防御塔是同时攻击的,因此选择型的防御塔不能够预判出该秒攻击是否多余,即最优目标是绝对的,不会因为其他塔能够射杀死中途改变;4.要注意最后全部怪兽被持续冻结而不掉血的情况。题目中可能没有把这个游戏的过程说的特别详细,对于每一秒钟是如下度过的:在一秒钟开始的时候(S)所有的怪兽全部获得一秒钟更新时间:如果怪兽被冻结,那么这一秒钟用于解冻,无法移动;否则使用一秒钟向
阅读全文
摘要:题意:给定一些歌词,歌词是一行一行给定的,要出输出出现次数大于2的所有单词,次数一样多的单词归为一组,每组输出长度最长的,否则输出字典序倒数第二的单词。解法:这题单词的定义实在是模糊,正确做法是把所有的非字母变为空格后再处理。使用map统计单词数量,然后用数组取出来排个序即可。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cctype>#include &l
阅读全文
摘要:题意:有一个判定用户等级的系统,现在不同的等级有不同的评价标准,现给定一个用户的历史等级以及当前最新的数据,要求给出目前的等级。解法:把不同的等级标题映射到数字,然后或者历史等级的标号,然后从大的往当前标号枚举,查看是否升级,如果升级则推出判定;否则从当前等级往小的标号枚举,查看是否降级,查看降级时只需要判定比率是否小于一个阀值即可,因为其他满足历史等级的条件一定满足标号比它小的等级,遇到不降级即退出判定。由于Peasant的判定于其他不太一样,在开始的时候就判定一下。代码如下:#include <cstdlib>#include <cstdio>#include &l
阅读全文
摘要:题意:比赛的时候想了各种的贪心方案,最后还是没有把这题搞出来......废话不多说,题目给定了一条条给定了顺序的路径,这些路径是后面要一一走过的,每条路径有一个长度,单位长度消耗汽油的量以及该条公路上加油站的汽油单价。告诉你路径条数N,油箱容积K,问如何安排加油是的行走完所有路径的花费最少。解法:该题有一个很巧妙的解法就是每到一个油站都加满油箱,队列里面保留了走过前面路径后保留的最便宜的油,每次从队列中取出最便宜的油行进这一段路程。在维持一个汽油价格单调递增时,具体过程如下:1.当队尾不为空时,每次从队尾向前遍历,如果元素单价高于当前路线加油站的汽油单价,替换之,知道遇到价格比其低的汽油或者队
阅读全文
摘要:题意:给定一系列的数码管,这些数码管由3*3的图形构成,相邻的两个数码管紧挨着的一列是重叠的,现在问一共有多少种可能的情况。解法:将每个数字的可能的显示结果(能亮的地方假设都可以亮)保留起来,然后一个一个数码枚举,一个地方要注意就是相邻意味前面一个数码占用了某一个亮线,那么后面这个数码可以选择是否占用该亮线,而如果前面没用占用该亮线则后面的数码必须占用。使用f[i][j]表示到第i个字符,占用相邻列情况为j时的方案数。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <
阅读全文
摘要:http://wenku.baidu.com/view/56c85dfafab069dc502201a3.html一道非常经典的割的应用。
阅读全文
摘要:题意:给定若干个房间,现在这些房间之间能够相互的联通,房间门是单向的,现在问一些门中都有人的情况下,至少要堵住多少条门才能够使得无法到达终点。解法:显然这是一个集合的分割问题,即求这样的一个割:使得终点房间与某些存在人的房间的一个分割,题中求的最少的人就是求解一个最小割。将问题转化为网络流求解。通过建立从超级源点到存在人的一些房间,那么从汇点反向遍历寻找这样的一个割。如果从源点到有人房间的边满流,那么反向遍历一定不会将这个节点划分到汇点集合里面去,如果该边不满流的话,如果划分到了汇点集合,则表明存在从源点到汇点的流量,于最大流相悖。因此所求既满足题意。代码如下:#include <cst
阅读全文
摘要:题意:给定N个点,M条边,每个点为0或者为1,每条边有一个权值。接下来有Q组操作,要么翻转某个点的标号,要么询问某组边的权值一共为多少,总共有三种类型的边:端点分别为(0, 0), (0, 1), (1, 1)。解法:这题的一个蛮力的解法就是记录好每一点的标号,然后O(1)的时间修改编号,对于每次查询就遍历所有的边进行询问。这样的话时间复杂度就是O(q*m)了,显然无法接受。换个好点的,我们首先通过原始数据在输入的时候处理一下,保留好每条边所属的类型。那么在没有点进行修改的话,O(1)时间进行输出。问题就是如果要进行修改的话,一个合理的方式就是修改当前节点所连的边的属性,因为其他于该节点无关的
阅读全文
摘要:题意:给定一个无向图,要求判定分离两个点的最小割是否唯一。解法:在求出最大流的基础上,从源点进行一次搜索,搜索按照未饱和的边进行,得到顶点子集S的顶点个数;再从汇点反向搜索未饱和的边,得到子集T的顶点个数,判定顶点数相加是否等于总共的顶点数。http://blog.csdn.net/waitfor_/article/details/7330437的文章写的很好,这里截取文中所画的两个图进行说明。(1)正向搜索集合为S,反向搜索集合为T,cnt1和cnt2都是最小割边。很显然M还存在着最小割边,因为从M到T的残余网络也没有流向T的容量了。(2)增加E1这部分边的容量将直接导致网络最大流量增加。增
阅读全文
摘要:题意:地球和火星发生了战争。现火星人要在一个N*M的网格降落他们的伞兵,而我们要消灭掉这些伞兵。有这样一种武器,它能够瞬间摧毁网格上某一行或者是某一列的所有目标。然而在哪一行或者哪一列部署这样的武器的花费是不同的。因此要求给出一种最省的方式使得所有的伞兵都能够被消灭。花费的定义是某种部署方案能够消灭所有伞兵,然后根据给定的行列费用把它们相乘即为。希望这一天永远不要到来吧。解法:首先这题应该让无数少男少女想到了二分匹配中做到的关于行列匹配的题吧。只不过这题中并不是所有的行和列等价。而是行列的权值各不相同。类比于原来问题中的最小顶点覆盖,这里就是一个最小点权覆盖,也即使用最小点权和的点集使得所有的
阅读全文
摘要:题意:给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路。解法:首先回顾下有向图的欧拉回路的条件是什么:所有的节点出度等于入度。现考虑到下面的这个图的转化过程:假设上方图中的A,B两点代表在有向图存在欧拉回路时任意两点之间连边关系,显然有两个点的入度等于出度。现在考虑改变某条边的关系,那么可以看到新的入度和出入如下图,这一有一个不变量就是任意一个点的入度和出度之差的奇偶性不变。现列步骤如下:1.为任意一条无向边选择一个方向。如果存在欧拉回路的话,那么可以得到每个点入度于出度差至少应满足为偶数。否则一定不能够构成欧拉回路。2.在满足上述条件的基础上,我们需要对
阅读全文