随笔分类 - ACM题解
摘要:亚洲区长春站网络赛第2题题意:Alice和Bob各有n张卡片,如果卡片a的宽和高都不小于卡片b,则a能覆盖b,问Alice的卡片最多能覆盖多少Bob的卡片。每张卡片只能用一次,每张最多只能覆盖一张。分析:在这里卡片之间的关系有3种,1、a能覆盖b;2、b能覆盖a;3、a不能覆盖b,b不也覆盖不了a(a和b相同的情况可以并入前面2种)。我们将双方卡片排序(先比较高,然后比较宽,小的在前)后,若Alice最小的卡片不能覆盖Bob最小的卡片,则Alice这张卡片可以直接抛弃,如果能覆盖,则一定要覆盖一个宽度最大的。我们将Bob的卡片中高度比它小的存入set(关键字为最大宽度-自身宽度),要注意相同卡
阅读全文
摘要:Problem Description:A peak number is defined as continuous digits {D0, D1 … Dn-1} (D0 > 0 and n >= 3), which exist Dm (0 < m < n - 1) satisfied Di-1 < Di (0 < i <= m) and Di > Di+1 (m <= i < n - 1).A number is called bi-peak if it is a concatenation of two peak numbers.
阅读全文
摘要:题意:求区间[x , y]中beautiful number的个数,a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits.分析:一个数能被它的所有非零数位整除,则能被它们的最小公倍数整除,而1到9的最小公倍数为2520,数位DP时我们只需保存前面那些位的最小公倍数就可进行状态转移,到边界时就把所有位的lcm求出了,为了判断这个数能否被它的所有数位整除,我们还需要这个数的值,显然要记录值是不可能的,其实我们只需记录它对2520的模即可,这样我们就可以设
阅读全文
摘要:题意:给m个字符串,求长为n且至少包含k个上述字符串的字符串有多少个。数据范围:(1<=n<=25),(0<=m<=10)分析:用dp[i][cur][s]表示走i步后,到达结点cur,包含的字符串压缩为状态s(第x位为1表示包含第x个字符串)的字符串有多少个。TLE:当dp[i-1][pre][s]=0时,直接continue,不用进入下一层循环,经此优化后就AC了。View Code #include <stdio.h>#include <string.h>#include <queue>using namespace std;#
阅读全文
摘要:题意:给n个01字符串,求区间[x , y]中有多少个数写成BCD码后不包含以上01串。分析:先用01字符串建立AC自动机(注意标记危险结点),然后DP。dp[i][s]表示扫描前i位后有多少个数会到达自动机的结点s.TLE:数位DP写搓了……(为此今天专门学习了下数位DP的dfs写法,发现确实比递推的快不少)WA:1、高精度减1写错了; 2、由于有取模,所以cal(y)可能小于cal(x-1),输出的时候没考虑到。View Code #include <stdio.h>#include <string.h>#include <queue>using nam
阅读全文
摘要:题意:求[x , y]中有多少个平衡数。平衡数:选定一位作为支点,若左右的力矩平衡则该数是平衡数,否则不是。For example, 4139 is a balanced number with pivot fixed at 3. The torqueses are 4*2 + 1*1 = 9 and 9*1 = 9View Code #include <stdio.h>#include <string.h>#define N 19#define M 1378typedef __int64 LL;LL dp[N][N][M];int digit[N];LL dfs(in
阅读全文
摘要:题意:求1-n中有多少个数含字符串”13"且能被13整除。(1 <= n <= 1000000000).练习数位DP的dfs写法。View Code #include <stdio.h>#include <string.h>#define N 10int dp[N][13][3],digit[N];int dfs(int pos,int r,int s,int f){ if(pos==-1) return r==0&&s==2; if(!f&&dp[pos][r][s]!=-1) return dp[pos][r][
阅读全文
摘要:题意:求1-N中有多少个数包含字符串"49"。1 <= N <= 2^63-1重写这题就是为了学习数位DP的dfs写法,感觉dfs的写法思路更清晰,速度也更快。View Code #include <stdio.h>#include <string.h>#define N 20typedef __int64 LL;LL dp[N][3];int digit[N];LL dfs(int pos,int s,int f){ if(pos==-1) return s==2; if(!f&&dp[pos][s]!=-1) retu
阅读全文
摘要:模型:给一个完全二部图,每条边都有一个权值,求边权和最大的匹配。数据范围:n<=250分析:直接套用KM算法即可,要加slack数组优化,优化后复杂度为O(N3)。View Code #include <stdio.h>#include <string.h>#define N 300#define INF 0x7fffffff#define MIN(a,b) ((a)<(b)?(a):(b))#define MAX(a,b) ((a)>(b)?(a):(b))int n,g[N][N];int x[N],y[N],lx[N],ly[N],match[N
阅读全文
摘要:题意:给一棵树,当在某个结点上放置士兵时,与该点相邻的边就被看守住了,求最少需多少士兵才能看住树中所有边。分析:先将无根树有根化,然后DP。状态设计: 1、dp[i][0],表示在结点 i 没放置士兵的情况下,看住以结点 i 为根的子树的所有边所需的最少士兵; 2、dp[i][1],表示在结点 i 放置士兵的情况下,看住以结点 i 为根的子树的所有边所需的最少士兵。状态转移: 1、dp[i][0]=∑dp[j][1],j 是 i 的儿子结点;(根结点不放士兵时,与其相连的边必须由儿子结点来看守) 2、dp[i][1]=1+∑ ( MIN ( dp[j][...
阅读全文
摘要:题意:给出N个词根,求长不超过L的且至少包含一个上述词根的单词的个数。数据范围:0<N<6,0<L<2^31这题与上一题差不多,但比上题要繁琐的多,关键的区别在于"不超过L" 和"至少包含一个"因为"至少包含一个",所以刚好是求上一题的反面;因为"不超过L",所以要求的是矩阵幂和S = A + A2 + A3 + … + AkView Code #include <stdio.h>#include <string.h>#include <queue>#in
阅读全文
摘要:题意:给出m个致病DNA片段,求长为n且不含致病片段的DNA序列共有多少种。数据范围:0 <= m <= 10,1 <= n <=2000000000这题初看起来与上一题差不多,但一看数据范围就傻了……分析:先建m个致病DNA片段的自动机,然后求出自动机中结点之间转移的路径数目,这样就可以得到一个有向图,所求问题就变为从根结点出发,到达任意一点,所走路径长度为n且路径不经过危险结点的路径数目。再抽象一下,就是求一个边长均为1的有向图中2点之间长为n的路径数目,这就不难想到矩阵了。设G为邻接矩阵,则Gk中第i行j列的元素表示从i到j长为k的路径数目。View Code #
阅读全文
摘要:题意:给出包含n个可见字符的字符集,以下所提字符串均由该字符集中的字符构成。给出p个长度不超过10的字符串,求长为m且不包含上述p个字符串的字符串有多少个。数据范围:1<=n,m<=50,0<=p<=10状态设计:dp[i][j],i 步之内未经过危险结点且第 i 步到达结点 j 的路径数目。状态转移:dp[i][j]=∑dp[i-1][k],在结点 k 加输入 s[i] 能跳到结点 j初始化:dp[0][0]=1,对于其余的 i :dp[0][i]=0注意:由于最后结果很大,而题中又没提到取模,所以要用到大数相加。View Code #include <stdi
阅读全文
摘要:题意:先给出m个DNA片段(含致病基因),然后给一个长为n的DNA序列,求最少需要修改多少次,使得这个DNA序列不含致病基因。修改操作定义为将DNA中某个碱基变为另一个碱基,如将A变为G数据范围:1<=m<=50,1<=n<=1000分析:先建自动机,然后DP。状态设计:dp[i][j]为从根结点出发走 i 步后到达状态 j 最少需要修改的次数。状态转移:1、dp[i][j]=MIN(dp[i-1][k]),从状态k能根据s[i]跳到状态j,无需修改;2、dp[i][j]=MIN(dp[i-1][k])+1,从状态k不能根据s[i]跳到状态j,需要修改s[i]。(注意区
阅读全文
摘要:题意:给出2个深搜过程,确定是否是对同一棵树的遍历。深搜过程是用01串来描述的,0代表远离树根,1代表靠近树根。分析:利用最小表示的思想,我们将树的所有结点按一定的规则排个序,然后比较2棵树的结点是否一样即可。排序规则:先按深度排序(离树根的距离),深度相同的按以该结点为根的子树结点数目排序。其实排序的过程就是统一遍历规则的过程,利用上面的规则排序后的结点是一个宽度优先的搜索顺序,且同一层中按后代结点数目小的先遍历。View Code #include <stdio.h>#include <stdlib.h>#include <string.h>#defin
阅读全文
摘要:题意:Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.分析:与矩阵快速幂的思想一样,都是二分。1、k为偶数,设k=2*m,则S = A + A2 + A3 + … + Am+(A + A2 + A3 + … + Am)*Am2、k为奇数,设k=2*m+1,则S = A + A2 + A3 + … + Am+(A + A2 + A3 + … + Am)*Am+Ak由上可见,原问题均可递归成与原问题结构相同的子问题,递归边界为k=1时,结果为AView Code
阅读全文
摘要:题意:给n个矩形,每个矩形都有一个矩形的“洞”,矩形和洞的边都与坐标轴平行,求这些带“洞”的矩形覆盖的面积。数据范围:n<=50000, 0<=x,y<=50000分析:这题本质还是求矩形面积并,因为一个带“洞”的矩形可以看成是4个矩形。由于矩形数目n和坐标范围均比较大,所以离散化+暴力统计的方法肯定会超时。扫描线的方法我也是第一次学,我的理解是这样的,把所有矩形的2条竖直边(横边也一样)无限延伸就得到扫描线,这些线把所有矩形重新划分为许多不相交的矩形,所有矩形的面积并其实就是夹在这些线之间的矩形的面积之和,夹缝中的矩形的宽就是扫描线之间的距离,关键在于夹缝中矩形的高度是多少
阅读全文
摘要:题意:在二维平面上给出n个矩形的顶点坐标(浮点数),每个矩形的边都平行坐标轴,求矩形覆盖的面积。数据范围:n<=100, 0=<x,y<=100000分析:由于n比较小,所以用离散化就能过(离散化的具体分析见上一篇)。View Code #include <stdio.h>#include <string.h>#include <stdlib.h>#define N 110int n;double xl[N],yl[N];double xr[N],yu[N];double x[2*N],y[2*N];int xcnt,ycnt;bool f
阅读全文
摘要:题意:在二维平面上给出n个矩形的坐标,矩形的边与x轴和y轴平行,求这n个矩形覆盖的面积。数据范围:n<=1000, x,y均为不大于50000的正整数分析:由于坐标都是整数的,我们可以把二维平面看成由面积都是1的小方格组成,最暴力的方法就是标记每个矩形覆盖的小方格,最后再统计一共有多少小方格被覆盖,但是坐标平面太大了,最坏情况下为50000*50000,肯定超时了。虽然坐标范围比较大,但是矩形个数却比较小,此时不难想到离散化,离散化后,我们不再将坐标平面划分为面积为1的小方格,而是根据在n个矩形中出现过的坐标来划分,这样的话,最后划分出来出来的方格数目不会超过2n*2n,这样就不会超时了
阅读全文
摘要:模型:给一个n个点的无向带权图,求从指定起点出发,经过指定的k个点(顺序不定)最后回到起点的最小代价。数据范围:n<=10^4, m<=10^5, k<15分析:先求最短路,求出从指定的k+1(含起点)个点到其他点的最小代价,然后建立k+1个点之间的最小代价邻接矩阵。最后用状态压缩DP求结果(状态压缩DP参考上一篇)。View Code #include <stdio.h>#include <string.h>#include <queue>using namespace std;#define MIN(a,b) ((a)<(b)?(
阅读全文

浙公网安备 33010602011771号