A
题意:判断一个字符串是否存在偶数长度回文子串。
思路:判断是否有两个字符相等即可。O(n)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
B
题意:总共n种字符,判断一个n*n的方格
(1)是否每行都包含n种字符,每一列是否都包含n种字符;
(2)在满足性质(1)的情况下判断第一行和第一列元素是否严格上升
思路:按上述题意模拟即可。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
C
题意:定义f(x)为x的约数个数,求SUM(f(x)) (a <= x <= b)
思路:枚举小于等于1e6的因子,对于每一个因子y, a 到 b之间能整出y的个数为 b/y(向下取整) - a/y(向上取整)+ 1,a 到 b 之间能整除y之后剩的因子为 b/y(向下取整), ..., a/y(向上取整)的公差为-1的等差数列。
因此,在最终答案中直接加上y的个数 * y 以及除y后剩的因子和即可。但为了保证每个y只被算一次,我们应该让除y后剩余间的左端点l = max(a/y(向上取整), y)。同时,在y == l时,不要加两次y。计算量为1e6.
没理解的话可以结合代码思考,感觉代码比文字表达更清晰。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
D
题意:定义一个序列 1, 1, 1, 1, 1, 1, ..., 2, 2, 2, 2, 2, 2, .....i, i, i, i, i, ..., n - 1 (每个数i连续出现n - i次), 求序列中间的那个数。
思路:对于每个数i,第一次出现的位置都可以O(1)求出来(等差数列求和),我们又可以求出序列总元素个数以及中间数的位置,因此二分判定就好了。O(logn)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
E
题意:已知一个机器人的速度,起点终点都在x轴方向,中间有一些竖向的传送带,各个速度都已知, 判定一下机器人到终点的最短时间。
思路:对y轴移动距离列方程,把机器人速度分解,vy * L / vx = SUM(vi * li / vx)。vx可以约掉。因此马上求出vy, vx也可以求出。复杂度O(n)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
F
题意:对于一个只有RB两种字符的字符串,求出一个子串使得‘R’, ‘B’两种字符数量的差值最大。
思路:可以将问题拆开。一种是求R的数量-B的数量最多,另一个是B的数量-R的数量最大。考虑每个单独的问题,比如要求R-B尽可能多,我们线性扫一遍,如果当前R的数量大于等于B,那么我们遇见R就加1, 遇见B就减1。
如果R比B少,那么我们为了使这个差值尽可能大,显然要舍弃之前选的那段序列,而从当前位置重新开始取。复杂度O(n)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
G
题意:一个有向图中每条边都有一段区间,表示权限,只有x在这段区间内才可以经过这条边,求出所有能从起点走到终点的x。
思路:我们把所有的区间统一改成左闭右开的形式。把所有的时间段的端点提取出来并从小到大排序。然后考虑每个时间点ti,如果ti能从起点到达终点,那么[t(i), t(i + 1))这段区间内的所有时间点都可以到达终点,因为如果t(i)可以到达终点,那么它肯定不能只是一个时间段的右开端点,所以他至少是一个左闭端点,因此其向后取的那一小段时间段一定可取;如果t(i)不能到达,则显然只是一个右开端点,因此不取它后面的一段区间。O(mlogm + m*(m + n))。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
H
题意:改变一个不均匀骰子的一个面的点数(可以为实数),使得其期望为3.5
思路:求出期望差值,除以概率最大的那个面就是改变的最小值。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
I
题意:一个无限长字符串上一系列插入删除操作,问两组操作是否等价。
思路:用个链表暴力n*n模拟?(这题我还没写,这几天写完更新)
UPDATE:
思路一:
确实是个链表模拟的n * n暴力,但比较麻烦。我的做法是链表上每个节点存一下到下一个节点的距离(距离定义为当前节点到下一个节点的左开右闭区间内字符个数),以及节点的虚实信息(虚节点定义为存在于最初串中并在之后被删除的元素,即遇见此类删除最初元素的情况,我们在链表中加入一个虚节点;实节点定义为之后插入的新元素;如果插入且之后被删除则我们不存储这类节点,在其被删除的时候也将该实节点从链表中删除)。至此,链表插入删除维护完毕。
但这样处理会产生问题,即等价的一系列操作会产生不同形式的最终链表(例子在代码最后的注释里)。因此我们在判断之前要对其进行统一化处理,格式之所以不统一是因为有一些地方可以合并但没有合并,所以我们合并所有能合并的地方(再次声明距离的定义是左开右闭区间内字符数量):(1)当前节点为虚节点,且距离下一节点为0,显然可以删掉(2)当前节点为实节点,且前一个节点为虚节点且距当前节点距离1,此时我们应删除前一个节点,并让新产生的前一个节点距离加1(3)其他所有情况都代表着两个节点之间有原序列中的元素,皆不可合并。
最后严格地判断两个链表中对应节点是否完全相等即可。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
思路二:
官方题解的做法,就是不用链表模拟,将所有的操作都统一成D i1, i2, ..., in, I j1, j2, ..., jm 的形式,其中i序列递减,j序列递增。类似冒泡排序按五类情况模拟即可。
J
题意:一个n * m的方格上有‘B’, 'R', '.'分别表示黑色,红色,以及目前为空着。要求每个B左上角的所有块都必须为黑色,R右下角的所有块都必须为红色。
思路:你可以先n*n*m*m暴力利用所有已知的R,B信息把方格填充,这样左上角以及右下角都被确定,待处理的只有中间空的一部分,这个中间部分满足列数从左到右时,其相应待确定的行数单调递减。
因此,我们用dp[j][i]表示第j列第i行为此列最后一个黑色块,那么dp[j][i] = SUM(dp[j - 1][k]),其中k从i到n。复杂度O(n * n * m * m),可以优化到O(n*m)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
K
题意:美国国旗是有s个星,所有奇数行星数都为x, 所有偶数行星数都为y, x等于y或y + 1。
思路:枚举三种情况,(1) x == y (2) x == y + 1总行数为偶数 (3) x == y + 1总行数为奇数。最后排下序,复杂度O(S + sqrt(s) * logs)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
L
题意:已知x, k, p, 求x * n + k * p / n的最小值
思路:对号函数,因为n为整数,输出sqrt(k * p / x)左右两个整点对应函数值的最小值。O(1)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code
M
题意:给一个n,求出大于n中第一个不含0的数。
思路:从n+1开始枚举即可,复杂度O(n / 10)。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include <string>
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include <set>
14 #include
View Code