20200213 第五场
进度(7/10) 未完成:-
A、模板
1、链接
https://ac.nowcoder.com/acm/contest/3006/A
2、题面
牛牛,牛可乐和牛能组成了一只队伍参加ACM系列赛事,他们起了一个优雅的队名叫~“牛牛战队”
牛可乐将试图通过以下操作用尽可能少的步骤把一个密钥转换为另一个:
- 将其中任意一个字母替换为另一个
- 把最后一个字母删除
- 在尾部添加一个字母
得到的转化步数就是最后的密码。
一天,你和他们队员一起聚餐,你用可乐把他们灌倒了,从牛牛和牛能口中套出了两个密钥。你要趁他们醒之前拿到模板并复印一份再放回去。你能尽快的算出密码吗?
3、思路
签到题。思路略。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define MAXN 100005 5 6 int n, m, ans; 7 char s1[MAXN], s2[MAXN]; 8 9 int main() { 10 cin >> n >> m >> s1 >> s2; 11 for (int i = 0; i < min(n, m); i++) 12 ans += s1[i] != s2[i]; 13 cout << ans + abs(n - m); 14 return 0; 15 }
B、牛牛战队的比赛地
1、链接
https://ac.nowcoder.com/acm/contest/3006/B
2、题面
由于牛牛战队经常要外出比赛,因此在全国各地建立了很多训练基地,每一个基地都有一个坐标(x,y)。
3、思路
我们设当前的最大距离为r,以每一个训练基地为圆心作半径为r的圆,圆与x轴的交点之间的弦中的所有点到该训练基地距离<=r。将所有的弦求出来,则所有的弦都重合的部分的所有点到所有训练基地距离都<=r。使所有弦恰好有重合部分(即两个或以上的弦正好交于某一点),此时r为最小值。
如图所示,p1为三段弦(其中C点与x轴相切)正好重合于A点,此时r = 2,即答案。p2中C点与x轴没有交点,显然这个距离根本到达不了C点,答案会更大;p3并非恰好重合,答案会更小。
根据这个思路,二分答案可以解决。
题解是三分法,不过我不太记得了。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define MAXN 100005 5 #define INF 0x3f3f3f3f 6 7 int n; 8 double x[MAXN], y[MAXN]; 9 10 int main() { 11 cin >> n; 12 for (int i = 1; i <= n; i++) 13 cin >> x[i] >> y[i], y[i] = abs(y[i]); 14 double l = 0, r = 100000000; 15 while (r - l > 1e-5) { 16 double m = (l + r) / 2, mi = INF, mx = -INF, f = 0; 17 for (int i = 1; i <= n; i++) { 18 if (y[i] > m) { 19 f = 1; 20 break; 21 } 22 double o = sqrt(m * m - y[i] * y[i]); 23 mi = min(mi, x[i] + o), mx = max(mx, x[i] - o); 24 } 25 if (mi >= mx && !f) r = m; 26 else l = m; 27 } 28 cout << l; 29 return 0; 30 }
D、牛牛与牛妹的约会
1、链接
https://ac.nowcoder.com/acm/contest/3006/D
2、题面
牛牛在辛苦的一天的比赛之后,要去找牛妹玩,其实牛妹那天也在比赛。他为了找到牛妹,要尽快的从自己的比赛地到她的比赛地。
还记得吗,比赛地都是只在x轴上的,所以两个人的坐标都满足y=0。牛牛除了可以以1单位距离/单位时间的速度移动任意时间以外,还可以花费1单位时间进行闪现。每次闪现时,如果当前他的坐标是x=k,他将闪现到k ^ (1/3)
请帮他算算,最短需要多少时间,他可以找到牛妹~
3、思路
两种移动的方式:一种直接走过去,耗时等同于距离;一种用跳刀跳过去,耗时为1,我们要考虑的就是什么情况下跳刀会比走过去更划得来,即走过去耗时大于1。
根据题意,跳刀只能变成自身的立方根,即如果是正数只能变小;如果是负数只能变大。我们将a和b所在的位置根据正负和大小关系分成6种情况讨论:
① a < b; a > 0, b > 0.
② a > b; a < 0, b < 0.
这两种情况最简单,因为跳刀被禁用了,所以 ans = abs(a - b)。
③ a < b; a < 0, b > 0.
④ a > b; a > 0, b < 0.
这两种情况可以将路程分成两部分处理,第一部分接近原点,正数变小负数变大,则需要考虑用跳刀;第二部分远离原点,直接走过去。
⑤ a < b; a < 0, b < 0.
⑥ a > b; a > 0, b > 0.
这两种情况,由于在同一侧,用跳刀不能过于贪心,因为你可能跳过身,这个时候要抉择是跳到她面前再走过去,还是跳到她身后再过去。就类似于坐公交车/地铁,如果你要去的地方在车站之间,你就需要考虑下是坐到前一站还是后一站了。
分析完6种情况,判定是用跳刀还是走过去其实就不难了,不做过多分析。
这题坑了我一次,现在才知道pow(a, b)中a不能为负数,因为编译器不会事先判定b的值,直接一刀切的不准a < 0了。那么对于本题就可以用-pow(-a, b)来解决这个问题。
然后fwl提供了个cbrt函数,太冷门了,真的没听过,查都查不到 Orz...
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int t; 5 6 int main() { 7 cin >> t; 8 for (int i = 1; i <= t; i++) { 9 double ans = 0, a, b; 10 cin >> a >> b; 11 if (a < b) { 12 if (a <= 0 && b >= 0) { 13 while (a + pow(-a, 1 / 3.0) < -1.0) a = -pow(-a, 1 / 3.0), ans += 1; 14 ans += b - a; 15 } 16 else if (a >= 0 && b >= 0) ans = b - a; 17 else if (a < 0 && b < 0) { 18 while (abs(-pow(-a, 1 / 3.0) - b) + 1 < abs(a - b)) a = -pow(-a, 1 / 3.0), ans += 1; 19 ans += abs(a - b); 20 } 21 } 22 else if (a > b) { 23 if (a >= 0 && b <= 0) { 24 while (a - pow(a, 1 / 3.0) > 1.0) a = pow(a, 1 / 3.0), ans += 1; 25 ans += a - b; 26 } 27 else if (a <= 0 && b <= 0) ans = a - b; 28 else if (a > 0 && b > 0) { 29 while (abs(pow(a, 1 / 3.0) - b) + 1 < abs(a - b)) a = pow(a, 1 / 3.0), ans += 1; 30 ans += abs(a - b); 31 } 32 } 33 else ans = 0; 34 printf("%.9lf\n", ans); 35 } 36 return 0; 37 }